home *** CD-ROM | disk | FTP | other *** search
- /* graph - graph a function of a single variable
-
- history...
- 9 Aug 85 Using box marker rather than plus, setting viewport based
- actual character width.
-
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <g.h>
- #include <g3.h>
-
- #define amax1(a,b) (((a)>(b))?(a):(b))
-
- #define ENTRIES 500
- #define MAXSTYLES 20
- #define MAXLAB 100
-
- #define RIGHT "copyright (c) 1985, James R. Van Zandt (jrv@mitre-bedford) \n"
- #define VERSION "1.4"
-
- double *x, *y;
- double xmin, xmax, xdel=0., ymin, ymax, ydel=0.;
- static double
- height_used=1., /* fraction of vertical space used */
- width_used=1., /* fraction of horizontal space used */
- right_move=0., /* fraction of space to move right before plotting */
- up_move=0., /* fraction of space to move up before plotting */
- abscissa=0., /* default starting value for automatic abscissas */
- abscissa_step=1.; /* default step for automatic abscissas */
-
- extern int debugging;
-
- int markers=0;
- int text_labeling=0;
- int numeric_labeling=1;
- int grid_style=1; /* 0 for no grid, 1 for frame with tics,
- 2 for full grid */
- int breaking=0; /* nonzero if breaking (disconnecting) graph
- after each label in input */
- int default_labeling=0; /* nonzero if default point label was given */
- int transposing=0; /* nonzero if transposing x & y */
- int logx=0; /* nonzero if x axis is to be logrithmic */
- int logy=0; /* nonzero if y axis is to be logrithmic */
- int x_arguments=0; /* number specified: xmin, xmax, xdel */
- int y_arguments=0; /* number specified: ymin, ymax, ydel */
- int style[MAXSTYLES]; /* array of requested line styles */
- int automatic_abscissas=0; /* nonzero if abscissas are to be generated */
- int abscissa_arguments=0; /* number specified: abscissa spacing & start */
- int last=0; /* number of entries in x and y */
- int labels=0; /* number of user-supplied labels
- (index into next two arrays) */
- int p_data[MAXLAB]; char *p_text[MAXLAB];
-
- FILE file;
-
- char *default_label="";
- char *text_label="";
-
- main(argc,argv) int argc; char **argv;
- { double lower, upper, delt, span;
- int nlab, ntic, i, j;
-
- read_data(argc,argv);
- initialize_core(0,0,2);
- initialize_view_surface(1);
- ndc_space_2(best_width,best_height);
- if(numeric_labeling)
- {right_move+=6./char_columns;
- width_used-=6./char_columns;
- up_move+=1.5/char_rows;
- height_used-=1.5/char_rows;
- }
- height_used*=best_height; up_move*=best_height;
- width_used*=best_width; right_move*=best_width;
- viewport2(right_move,right_move+width_used,up_move,up_move+height_used);
- clip_window(1);
- {
- /* printf("requesting x=%f to %f, y=%f to %f \n",xmin,xmax,ymin,ymax);
- getchar();
- */
- scale(xmin, xmax, logx, ymin, ymax, logy);
- inquire_window(&xmin, &xmax, &ymin, &ymax);
- /* printf("plotting x=%f to %f, y=%f to %f \n",xmin,xmax,ymin,ymax);
- getchar();
- */
- create_temporary_segment();
- image(); /* generate the figure */
- if(text_labeling)
- {move_abs_2(.9*xmin+.1*xmax,.92*ymax+.08*ymin);
- text(text_label);
- }
- axis(numeric_labeling,grid_style);
- close_temporary_segment();
- gotoxy(0,0);
- if(file==stdin) exit();
- getchar();
- }
- terminate_view_surface(1); exit();
- }
-
- read_data(argc,argv) int argc; char **argv;
- { int i,j,length;
- double xx,yy,d,*pd;
- double actual_xmin,actual_xmax,actual_ymin,actual_ymax;
- char *s,*t;
- #define BUFSIZE 200
- static char buf[BUFSIZE];
-
- x=malloc(ENTRIES*sizeof(double));
- y=malloc(ENTRIES*sizeof(double));
- if(x==0 || y==0) {puts("can\'t allocate buffer"); exit();}
- for(i=MAXSTYLES; i; ) style[--i]=1;
- p_data[0]=-1;
- if(argc>1 && streq(argv[1],"?")) help();
- if(argc<=1 || *argv[1]=='-') file=stdin;
- else
- {if(argc>1)
- {file=fopen(argv[1],"r");
- if(file==0) {printf("file %s not found\n",argv[1]); exit();}
- argc--; argv++;
- }
- else help();
- }
- argc--; argv++;
- actual_xmin=actual_ymin=1.e50;
- actual_xmax=actual_ymax=-1.e50;
- while(argc>0)
- {/* printf("read_data: parsing \"%s\" \n",*argv); */
- i=get_parameter(argc,argv);
- argv=argv+i; argc=argc-i;
- }
- if(automatic_abscissas && abscissa_arguments==0 && x_arguments)
- {abscissa=xmin;
- }
- for(i=0; i<ENTRIES; i++)
- {if(fgets(buf,BUFSIZE,file)==0) break;
- buf[strlen(buf)-1]=0;
- if(automatic_abscissas)
- {x[i]=abscissa;
- abscissa+=abscissa_step;
- sscanf(buf,"%F",&y[i]);
- }
- else
- {sscanf(buf,"%F %F",&x[i],&y[i]);
- }
- s=buf;
- /* printf("line %d is [%s], with length %d \n",i,s,strlen(s));*/
- while(*s==' ')s++; /* skip first number */
- while(*s && (*s!=' '))s++;
- if(!automatic_abscissas) /* skip second number */
- {while(*s==' ')s++;
- while(*s && (*s!=' '))s++;
- }
- while(*s==' ')s++;
- /* printf("line %d after numbers is [%s], with length %d \n",
- i,s,strlen(s)); */
- if((length=strlen(s))&&(labels<MAXLAB))
- {if(*s=='\"')
- {t=++s;
- while(*t && (*t!='\"')) t++;
- }
- else
- {t=s;
- while(*t && (*t!=' '))t++;
- }
- *t=0;
- length=t-s;
- p_data[labels]=i;
- p_text[labels]=malloc(length+1);
- if(p_text[labels]) strcpy(p_text[labels++],s);
- }
- if(logx && !automatic_abscissas)
- {if(x[i]<=0.) gripe_negative(); x[i]=log10(x[i]);
- }
- if(logy) {if(y[i]<=0.) gripe_negative(); y[i]=log10(y[i]);}
- if(x[i]<actual_xmin)actual_xmin=x[i];
- if(y[i]<actual_ymin)actual_ymin=y[i];
-
- if(x[i]>actual_xmax)actual_xmax=x[i];
- if(y[i]>actual_ymax)actual_ymax=y[i];
- }
- switch(x_arguments)
- {case 0: xmin=actual_xmin;
- case 1: xmax=actual_xmax;
- case 2: ;
- case 3: ;
- default: ;
- }
- switch(y_arguments)
- {case 0: ymin=actual_ymin;
- case 1: ymax=actual_ymax;
- case 2: ;
- case 3: ;
- default: ;
- }
- last=i-1;
- if(transposing)
- {i=logx; logx=logy; logy=i;
- i=x_arguments; x_arguments=y_arguments; y_arguments=i;
- pd=x; x=y; y=pd;
- d=xmin; xmin=ymin; ymin=d;
- d=xmax; xmax=ymax; ymax=d;
- d=xdel; xdel=ydel; ydel=d;
- }
- }
-
- image()
- { int i, j, k, st, segment;
-
- for(segment=i=0; i<=last; segment++)
- {j=style[segment];
- if(j>0)
- {if(st=j%10) st--;
- set_linestyle(st); j/=10;
- set_color(max_color-j%10); j/=10;
- set_linewidth(j);
- move_abs_2(x[i],y[i]);
- markers=0;
- }
- else
- {set_marker_symbol(j ? -j : 6);
- k=max_color-(-j)/10;
- set_color(j ? k : max_color);
- markers=1;
- }
- while(i<=last)
- {if(markers)marker_abs_2(x[i],y[i]);
- else line_abs_2(x[i],y[i]);
- if(i++ ==p_data[segment])
- {text(p_text[segment]);
- if(breaking) break;
- else segment++;
- }
- else if(default_labeling) text(default_label);
- }
- }
- set_linewidth(1);
- set_linestyle(0);
- set_color(7);
- }
-
- /* get_parameter - process one command line option
- (return # parameters used) */
- get_parameter(argc,argv) int argc; char **argv;
- { int i;
- if(streq(*argv,"-a"))
- {i=axis_arg(argc,argv,&abscissa_step,&abscissa,&i);
- abscissa_arguments=i-1;
- automatic_abscissas=1;
- return i;
- }
- else if(streq(*argv,"-b")) {breaking=1; return 1;}
- else if(streq(*argv,"-c"))
- {if(argc>1) {default_labeling=1; default_label=argv[1]; return 2;}
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-d")) {debugging=1; return 1;}
- else if(streq(*argv,"-g"))
- {if(argc>1 && numeric(argv[1]))
- {grid_style=atoi(argv[1]); return 2;
- }
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-h"))
- {if(argc>1 && numeric(argv[1]))
- {height_used=atof(argv[1]); return 2;
- }
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-l"))
- {if(argc>1) {text_labeling=1; text_label=argv[1]; return 2;}
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-r"))
- {if(argc>1 && numeric(argv[1]))
- {right_move=atof(argv[1]); return 2;
- }
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-t")) {transposing=1; return 1;}
- else if(streq(*argv,"-u"))
- {if(argc>1 && numeric(argv[1]))
- {up_move=atof(argv[1]); return 2;
- }
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-w"))
- {if(argc>1 && numeric(argv[1]))
- {width_used=atof(argv[1]); return 2;
- }
- else gripe_arg(argv[0]);
- }
- else if(streq(*argv,"-n")) {numeric_labeling=0; return 1;}
- else if(streq(*argv,"-m"))
- {i=1;
- while((argc>i) && numeric(argv[i]) && i<=MAXSTYLES)
- {style[i-1]=atoi(argv[i]); i++;}
- return i;
- }
- else if(streq(*argv,"-x"))
- {i=axis_arg(argc,argv,&xmin,&xmax,&xdel);
- x_arguments=i-1;
- return i;
- }
- else if(streq(*argv,"-y"))
- {i=axis_arg(argc,argv,&ymin,&ymax,&ydel);
- y_arguments=i-1;
- return i;
- }
- else if(streq(*argv,"-xl"))
- {i=axis_arg(argc,argv,&xmin,&xmax,&xdel);
- x_arguments=i-1;
- /* printf("before taking log: xmin=%f, xmax=%f, xdel=%f \n",
- xmin,xmax,xdel);
- */
- if(i>1) take_log(&xmin);
- if(i>2) take_log(&xmax);
- if(i>3) take_log(&xdel);
- /* printf("after taking log: xmin=%f, xmax=%f, xdel=%f \n",
- xmin,xmax,xdel);
- */
- logx=1;
- return i;
- }
- else if(streq(*argv,"-yl"))
- {i=axis_arg(argc,argv,&ymin,&ymax,&ydel);
- y_arguments=i-1;
- logy=1;
- if(i>1) take_log(&ymin);
- if(i>2) take_log(&ymax);
- if(i>3) take_log(&ydel);
- return i;
- }
- else gripe(argv);
- }
-
- axis_arg(argc,argv,qmin,qmax,qdel)
- int argc; char **argv; double *qmin,*qmax,*qdel;
- { int i=1;
- if((argc>i) && numeric(argv[i])) *qmin=atof(argv[i++]);
- if((argc>i) && numeric(argv[i])) *qmax=atof(argv[i++]);
- if((argc>i) && numeric(argv[i])) *qdel=atof(argv[i++]);
- return i;
- }
-
- int streq(a,b) char *a,*b;
- { while(*a)
- {if(*a!=*b)return 0;
- a++; b++;
- }
- return 1;
- }
-
- gripe_arg(s) char *s;
- { printf("argument missing for switch %s",s);
- help();
- }
-
- gripe_negative()
- { puts("nonpositive value along logrithmic axis ");
- exit();
- }
-
- gripe(argv) char **argv;
- { puts(*argv); puts(" isn\'t a legal argument \n\n");
- help();
- }
-
- help()
- { puts("sample usage... graph [data_file] [options]\n");
- puts("options are:\n");
- puts(" -a [step [start]] automatic abscissas \n");
- puts(" -b break graph after each label \n");
- puts(" -c <text> default label for points \n");
- puts(" -g grid style: 0=none 1=frame 2=full \n");
- puts(" -h <num> fraction of screen height to use\n");
- puts(" -r <num> fraction of screen to move right before plotting\n");
- puts(" -l <text> label for graph \n");
- puts(" -m n1 n2 n3... ni=0 for markers or nonzero for line styles: \n");
- puts(" ni=WCS, where W=width, C=color, S=dash style \n");
- puts(" -n omit numbers on axes \n");
- puts(" -t transpose x & y \n");
- puts(" -u <num> fraction of screen to move up before plotting\n");
- puts(" -w <num> fraction of screen width to use\n");
- puts(" -x[l] [min [max]] l signals log axis,\n");
- puts(" x axis extends from min to max \n");
- puts(" -y[l] [min [max]] similar for y axis\n\n");
- printf("Version %s for %s \n",VERSION,machine);
- puts(RIGHT);
- exit();
- }
-
- numeric(s) char *s;
- { char c;
- while(c=*s++)
- {if((c<='9' && c>='0') || c=='+' || c=='-' || c=='.') continue;
- return 0;
- }
- return 1;
- }
-
- take_log(q) double *q;
- { if(*q>0.) *q=log10(*q);
- else {printf("nonpositive argument %f for log axis",*q); exit();}
- }