home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * G N U P L O T -- graphics.c
- *
- * Copyright (C) 1986, 1987 Thomas Williams, Colin Kelley
- *
- * You may use this code as you wish if credit is given and this message
- * is retained.
- *
- * Please e-mail any useful additions to vu-vlsi!plot so they may be
- * included in later releases.
- *
- * This file should be edited with 4-column tabs! (:set ts=4 sw=4 in vi)
- */
-
- #include <stdio.h>
- #include <math.h>
- #include "plot.h"
-
- char *strcpy(),*strncpy(),*strcat();
-
- extern BOOLEAN polar;
- extern BOOLEAN autoscale;
- extern FILE *outfile;
- extern BOOLEAN log_x, log_y;
- extern int term;
-
- extern BOOLEAN screen_ok;
- extern BOOLEAN term_init;
-
- extern double loff,roff,toff,boff;
- extern double zero;
-
- extern struct termentry term_tbl[];
-
-
- #ifndef max /* Lattice C has max() in math.h, but shouldn't! */
- #define max(a,b) ((a > b) ? a : b)
- #endif
-
- /* maps floating point x (and y) to screen */
- #define map_x(x) (int)((x-xmin)*xscale)
- #define map_y(y) (int)((y-ymin)*yscale)
-
-
- double raise(x,y)
- double x;
- int y;
- {
- register int i;
- double val;
-
- val = 1.0;
- for (i=0; i < abs(y); i++)
- val *= x;
- if (y < 0 ) return (1.0/val);
- return(val);
- }
-
-
- double make_tics(tmin,tmax,logscale)
- double tmin,tmax;
- BOOLEAN logscale;
- {
- register double xr,xnorm,tics,tic,l10;
-
- xr = fabs(tmin-tmax);
-
- l10 = log10(xr);
- if (logscale) {
- tic = raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
- if (tic < 1.0)
- tic = 1.0;
- } else {
- xnorm = pow(10.0,l10-(double)((l10 >= 0.0 ) ? (int)l10 : ((int)l10-1)));
- if (xnorm <= 2)
- tics = 0.2;
- else if (xnorm <= 5)
- tics = 0.5;
- else tics = 1.0;
- tic = tics * raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
- }
- return(tic);
- }
-
- char *idx(a,b)
- char *a,b;
- {
- do {
- if (*a == b)
- return(a);
- } while (*a++);
- return(0);
- }
-
-
- num2str(num,str)
- double num;
- char str[];
- {
- static char temp[80];
- register double d;
- register char *a,*b;
-
- if ((d = fabs(num)) > 9999.0 || d < 0.001 && d != 0.0)
- (void) sprintf(temp,"%-.3e",num);
- else
- (void) sprintf(temp,"%-.3g",num);
- if (b = idx(temp,'e')) {
- a = b;
- while ( *(--a) == '0') /* trailing zeros */
- ;
- if ( *a == '.')
- a--;
- (void) strncpy(str,temp,(int)(a-temp)+1);
- str[(int)(a-temp)+1] = '\0';
- a = b+1; /* point to 1 after 'e' */
- (void) strcat(str,"e");
- if ( *a == '-')
- (void) strcat(str,"-");
- a++; /* advance a past '+' or '-' */
- while ( *a == '0' && *(a+1) != '\0') /* leading zeroes */
- a++;
- (void) strcat(str,a); /* copy rest of string */
- }
- else
- (void) strcpy(str,temp);
- }
-
-
- do_plot(plots, pcount, xmin, xmax, ymin, ymax)
- struct curve_points *plots;
- int pcount; /* count of plots in linked list */
- double xmin, xmax;
- double ymin, ymax;
- {
- register int i, x;
- register struct termentry *t = &term_tbl[term];
- register BOOLEAN prev_undef;
- register int curve, xaxis_y, yaxis_x, dpcount;
- register struct curve_points *this_plot;
- register enum PLOT_TYPE p_type;
- register double xscale, yscale;
- register double ytic, xtic, least, most, ticplace;
- register int mms,mts;
- /* only a Pyramid would have this many registers! */
- static char xns[20],xms[20],yns[20],yms[20],xts[20],yts[20];
- static char label[80];
-
- if (polar)
- polar_xform (plots, pcount, &xmin, &xmax, &ymin, &ymax);
-
- if (ymin == HUGE || ymax == -HUGE)
- int_error("all points undefined!", NO_CARET);
-
- /* This used be xmax == xmin, but that caused an infinite loop once. */
- if (fabs(xmax - xmin) < zero)
- int_error("xmin should not equal xmax!",NO_CARET);
- if (fabs(ymax - ymin) < zero)
- int_error("ymin should not equal ymax!",NO_CARET);
-
- /* Apply the desired viewport offsets. */
- xmin -= loff;
- xmax += roff;
- ymin -= boff;
- ymax += toff;
-
- ytic = make_tics(ymin,ymax,log_y);
- xtic = make_tics(xmin,xmax,log_x);
- dpcount = 0;
-
- if (ymin < ymax ) {
- ymin = ytic * floor(ymin/ytic);
- ymax = ytic * ceil(ymax/ytic);
- }
- else {
- ymin = ytic * ceil(ymin/ytic);
- ymax = ytic * floor(ymax/ytic);
- }
-
- yscale = (t->ymax - 2)/(ymax - ymin);
- xscale = (t->xmax - 2)/(xmax - xmin);
-
- if (!term_init) {
- (*t->init)();
- term_init = TRUE;
- }
- screen_ok = FALSE;
- (*t->graphics)();
- (*t->linetype)(-2); /* border linetype */
-
- /* draw plot border */
- (*t->move)(0,0);
- (*t->vector)(t->xmax-1,0);
- (*t->vector)(t->xmax-1,t->ymax-1);
- (*t->vector)(0,t->ymax-1);
- (*t->vector)(0,0);
-
- least = (ymin < ymax) ? ymin : ymax;
- most = (ymin < ymax) ? ymax : ymin;
-
- for (ticplace = ytic + least; ticplace < most ; ticplace += ytic) {
- (*t->move)(0,map_y(ticplace));
- (*t->vector)(t->h_tic,map_y(ticplace));
- (*t->move)(t->xmax-1,map_y(ticplace));
- (*t->vector)(t->xmax-1-t->h_tic,map_y(ticplace));
- }
-
- if (xmin < xmax ) {
- least = xtic * floor(xmin/xtic);
- most = xtic * ceil(xmax/xtic);
- }
- else {
- least = xtic * ceil(xmin/xtic);
- most = xtic * floor(xmax/xtic);
- }
-
- for (ticplace = xtic + least; ticplace < most ; ticplace += xtic) {
- (*t->move)(map_x(ticplace),0);
- (*t->vector)(map_x(ticplace),t->v_tic);
- (*t->move)(map_x(ticplace),t->ymax-1);
- (*t->vector)(map_x(ticplace),t->ymax-1-t->v_tic);
- }
-
- if (log_x) {
- num2str(pow(10.0,xmin),xns);
- num2str(pow(10.0,xmax),xms);
- num2str(pow(10.0,xtic),xts);
- }
- else {
- num2str(xmin,xns);
- num2str(xmax,xms);
- num2str(xtic,xts);
- }
- if (log_y) {
- num2str(pow(10.0,ymin),yns);
- num2str(pow(10.0,ymax),yms);
- num2str(pow(10.0,ytic),yts);
- } else {
- num2str(ymin,yns);
- num2str(ymax,yms);
- num2str(ytic,yts);
- }
- mms = max(strlen(xms),strlen(yms));
- mts = max(strlen(xts),strlen(yts));
-
- (void) sprintf(label,"%s < y < %-*s inc = %-*s",yns,mms,yms,mts,yts);
- (*t->lrput_text)(0, label);
- (void) sprintf(label,"%s < x < %-*s inc = %-*s",xns,mms,xms,mts,xts);
- (*t->lrput_text)(1, label);
-
-
- /* DRAW AXES */
- (*t->linetype)(-1); /* axis line type */
- xaxis_y = map_y(0.0);
- yaxis_x = map_x(0.0);
-
- if (xaxis_y < 0)
- xaxis_y = 0; /* save for impulse plotting */
- else if (xaxis_y >= t->ymax)
- xaxis_y = t->ymax - 1;
- else if (!log_y) {
- (*t->move)(0,xaxis_y);
- (*t->vector)((t->xmax-1),xaxis_y);
- }
-
- if (!log_x && yaxis_x >= 0 && yaxis_x < t->xmax) {
- (*t->move)(yaxis_x,0);
- (*t->vector)(yaxis_x,(t->ymax-1));
- }
-
- /* DRAW CURVES */
- this_plot = plots;
- for (curve = 0; curve < pcount; this_plot = this_plot->next_cp, curve++) {
- (*t->linetype)(curve);
- (*t->ulput_text)(curve, this_plot->title);
- (*t->linetype)(curve);
-
- p_type = this_plot->plot_type;
- switch(this_plot->plot_style) {
- case IMPULSES:
- for (i = 0; i < this_plot->p_count; i++) {
- if (!this_plot->points[i].undefined) {
- x = map_x(this_plot->points[i].x);
- (*t->move)(x,xaxis_y);
- (*t->vector)(x,map_y(this_plot->points[i].y));
- }
- }
- break;
- case LINES:
- prev_undef = TRUE;
- for (i = 0; i < this_plot->p_count; i++) {
- if (!this_plot->points[i].undefined) {
- x = map_x(this_plot->points[i].x);
- if (prev_undef)
- (*t->move)(x,
- map_y(this_plot->points[i].y));
- (*t->vector)(x,
- map_y(this_plot->points[i].y));
- }
- prev_undef = this_plot->points[i].undefined;
- }
- break;
- case POINTS:
- for (i = 0; i < this_plot->p_count; i++) {
- if (!this_plot->points[i].undefined) {
- x = map_x(this_plot->points[i].x);
- (*t->point)(x,map_y(this_plot->points[i].y),dpcount);
- }
- }
- dpcount++;
- break;
- }
- }
- (*t->text)();
- (void) fflush(outfile);
- }
-
-
- polar_xform (plots, pcount, xminp, xmaxp, yminp, ymaxp)
- struct curve_points *plots;
- int pcount; /* count of plots in linked list */
- double *xminp, *xmaxp;
- double *yminp, *ymaxp;
- {
- register int i, p_cnt;
- register struct termentry *t = &term_tbl[term];
- register struct curve_points *this_plot;
- enum PLOT_TYPE p_type;
- struct coordinate *pnts;
- int curve, xaxis_y, yaxis_x, dpcount;
- double xmin, xmax, ymin, ymax, x, y;
-
- /*
- Cycle through all the plots converting polar to rectangular and adjust
- max and mins.
- */
- xmin = HUGE;
- ymin = HUGE;
- xmax = -HUGE;
- ymax = -HUGE;
-
- this_plot = plots;
- for (curve = 0; curve < pcount; this_plot = this_plot->next_cp, curve++) {
- p_cnt = this_plot->p_count;
- pnts = this_plot->points;
-
- /* Convert to cartesian all points in this curve. */
- for (i = 0; i < p_cnt; i++) {
- if (!pnts[i].undefined) {
- x = pnts[i].y*cos(pnts[i].x);
- y = pnts[i].y*sin(pnts[i].x);
- pnts[i].x = x;
- pnts[i].y = y;
- if (xmin > x) xmin = x;
- if (xmax < x) xmax = x;
- /* Can't worry about autoscale (assume true). */
- if (ymin > y) ymin = y;
- if (ymax < y) ymax = y;
- }
- }
- }
- if (xmin < xmax) { /* All points might be undefined... */
- if (xmax - xmin < zero) {
- /* This happens at least for the plot of 1/cos(x) (verticle line). */
- xmin -= 3.14159;
- xmax += 3.14159;
- }
- }
- if (ymin < ymax) { /* Only if there were defined points... */
- if (ymax - ymin < zero) {
- /* This happens at least for the plot of 1/sin(x) (horizontal line). */
- ymin -= 1;
- ymax += 1;
- }
- }
-
- /* Return the new maximums and minimums */
- *xminp = xmin;
- *xmaxp = xmax;
- *yminp = ymin;
- *ymaxp = ymax;
- }
-