home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / coregraf / graph.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-01-06  |  11.1 KB  |  408 lines

  1. /*    graph - graph a function of a single variable
  2.  
  3.     history...
  4.         9 Aug 85    Using box marker rather than plus, setting viewport based
  5.                     actual character width.
  6.  
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <math.h>
  11. #include <g.h>
  12. #include <g3.h>
  13.  
  14. #define amax1(a,b) (((a)>(b))?(a):(b))
  15.  
  16. #define ENTRIES 500
  17. #define MAXSTYLES 20
  18. #define MAXLAB 100
  19.  
  20. #define RIGHT "copyright (c) 1985, James R. Van Zandt (jrv@mitre-bedford) \n"
  21. #define VERSION "1.4"
  22.  
  23. double *x, *y;
  24. double xmin, xmax, xdel=0., ymin, ymax, ydel=0.;
  25. static double
  26.     height_used=1.,        /* fraction of vertical space used */
  27.     width_used=1.,        /* fraction of horizontal space used    */
  28.     right_move=0.,        /* fraction of space to move right before plotting */
  29.     up_move=0.,            /* fraction of space to move up before plotting */
  30.     abscissa=0.,        /* default starting value for automatic abscissas */
  31.     abscissa_step=1.;    /* default step for automatic abscissas */
  32.  
  33. extern int    debugging;
  34.  
  35. int    markers=0;
  36. int text_labeling=0;
  37. int numeric_labeling=1;
  38. int grid_style=1;            /* 0 for no grid, 1 for frame with tics,
  39.                                 2 for full grid */
  40. int breaking=0;                /* nonzero if breaking (disconnecting) graph
  41.                                 after each label in input */
  42. int default_labeling=0;    /* nonzero if default point label was given */
  43. int transposing=0;            /* nonzero if transposing x & y */
  44. int logx=0;                    /* nonzero if x axis is to be logrithmic */
  45. int logy=0;                    /* nonzero if y axis is to be logrithmic */
  46. int x_arguments=0;            /* number specified: xmin, xmax, xdel    */
  47. int y_arguments=0;            /* number specified: ymin, ymax, ydel    */
  48. int style[MAXSTYLES];        /* array of requested line styles    */
  49. int automatic_abscissas=0;    /* nonzero if abscissas are to be generated */
  50. int abscissa_arguments=0;    /* number specified: abscissa spacing & start */
  51. int last=0;                    /* number of entries in x and y */
  52. int labels=0;                /* number of user-supplied labels
  53.                                  (index into next two arrays) */
  54. int p_data[MAXLAB]; char *p_text[MAXLAB];
  55.  
  56. FILE file;
  57.  
  58. char *default_label="";
  59. char *text_label="";
  60.  
  61. main(argc,argv) int argc; char **argv;
  62. {    double lower, upper, delt, span;
  63.     int nlab, ntic, i, j;
  64.  
  65.     read_data(argc,argv);
  66.     initialize_core(0,0,2);
  67.     initialize_view_surface(1);
  68.     ndc_space_2(best_width,best_height);
  69.     if(numeric_labeling)
  70.         {right_move+=6./char_columns;
  71.         width_used-=6./char_columns;
  72.         up_move+=1.5/char_rows;
  73.         height_used-=1.5/char_rows;
  74.         }
  75.     height_used*=best_height; up_move*=best_height;
  76.     width_used*=best_width;    right_move*=best_width;
  77.     viewport2(right_move,right_move+width_used,up_move,up_move+height_used);
  78.     clip_window(1);
  79.             {
  80. /*            printf("requesting x=%f to %f, y=%f to %f \n",xmin,xmax,ymin,ymax);
  81.             getchar();
  82. */
  83.             scale(xmin, xmax, logx, ymin, ymax, logy);
  84.             inquire_window(&xmin, &xmax, &ymin, &ymax);
  85. /*            printf("plotting   x=%f to %f, y=%f to %f \n",xmin,xmax,ymin,ymax);
  86.             getchar();
  87. */
  88.             create_temporary_segment();
  89.             image();    /* generate the figure */
  90.             if(text_labeling)
  91.                 {move_abs_2(.9*xmin+.1*xmax,.92*ymax+.08*ymin);
  92.                 text(text_label);
  93.                 }
  94.             axis(numeric_labeling,grid_style);
  95.             close_temporary_segment();
  96.             gotoxy(0,0);
  97.             if(file==stdin) exit();
  98.             getchar();
  99.             }
  100.     terminate_view_surface(1); exit();
  101. }
  102.  
  103. read_data(argc,argv) int argc; char **argv;
  104. {    int i,j,length;
  105.     double xx,yy,d,*pd;
  106.     double actual_xmin,actual_xmax,actual_ymin,actual_ymax;
  107.     char *s,*t;
  108. #define BUFSIZE 200
  109.     static char buf[BUFSIZE];
  110.  
  111.     x=malloc(ENTRIES*sizeof(double));
  112.     y=malloc(ENTRIES*sizeof(double));
  113.     if(x==0 || y==0) {puts("can\'t allocate buffer"); exit();}
  114.     for(i=MAXSTYLES; i; ) style[--i]=1;
  115.     p_data[0]=-1;
  116.     if(argc>1 && streq(argv[1],"?")) help();
  117.     if(argc<=1 || *argv[1]=='-') file=stdin;
  118.     else
  119.         {if(argc>1)
  120.             {file=fopen(argv[1],"r");
  121.             if(file==0) {printf("file %s not found\n",argv[1]); exit();}
  122.             argc--; argv++;
  123.             }
  124.         else help();
  125.         }
  126.     argc--; argv++;
  127.     actual_xmin=actual_ymin=1.e50;
  128.     actual_xmax=actual_ymax=-1.e50;
  129.     while(argc>0)
  130.         {/* printf("read_data: parsing \"%s\" \n",*argv); */
  131.         i=get_parameter(argc,argv);
  132.         argv=argv+i; argc=argc-i;
  133.         }
  134.     if(automatic_abscissas && abscissa_arguments==0 && x_arguments)
  135.         {abscissa=xmin;
  136.         }
  137.     for(i=0; i<ENTRIES; i++)
  138.         {if(fgets(buf,BUFSIZE,file)==0) break;
  139.         buf[strlen(buf)-1]=0;
  140.         if(automatic_abscissas)
  141.             {x[i]=abscissa;
  142.             abscissa+=abscissa_step;
  143.             sscanf(buf,"%F",&y[i]);
  144.             }
  145.         else
  146.             {sscanf(buf,"%F %F",&x[i],&y[i]);
  147.             }
  148.         s=buf;
  149. /*        printf("line %d is [%s], with length %d \n",i,s,strlen(s));*/
  150.         while(*s==' ')s++;                        /* skip first number */
  151.         while(*s && (*s!=' '))s++;
  152.         if(!automatic_abscissas)                /* skip second number */
  153.             {while(*s==' ')s++;
  154.             while(*s && (*s!=' '))s++;
  155.             }
  156.         while(*s==' ')s++;
  157. /*        printf("line %d after numbers is [%s], with length %d \n",
  158.         i,s,strlen(s)); */
  159.         if((length=strlen(s))&&(labels<MAXLAB))
  160.             {if(*s=='\"')
  161.                 {t=++s;
  162.                 while(*t && (*t!='\"')) t++;
  163.                 }
  164.             else
  165.                 {t=s;
  166.                 while(*t && (*t!=' '))t++;
  167.                 }
  168.             *t=0;
  169.             length=t-s;
  170.             p_data[labels]=i;
  171.             p_text[labels]=malloc(length+1);
  172.             if(p_text[labels]) strcpy(p_text[labels++],s);
  173.             }
  174.         if(logx && !automatic_abscissas)
  175.             {if(x[i]<=0.) gripe_negative(); x[i]=log10(x[i]);
  176.             }
  177.         if(logy) {if(y[i]<=0.) gripe_negative(); y[i]=log10(y[i]);}
  178.         if(x[i]<actual_xmin)actual_xmin=x[i];
  179.         if(y[i]<actual_ymin)actual_ymin=y[i];
  180.  
  181.         if(x[i]>actual_xmax)actual_xmax=x[i];
  182.         if(y[i]>actual_ymax)actual_ymax=y[i];
  183.         }
  184.     switch(x_arguments)
  185.         {case 0:    xmin=actual_xmin;
  186.         case 1:        xmax=actual_xmax;
  187.         case 2:        ;
  188.         case 3:        ;
  189.         default:    ;
  190.         }
  191.     switch(y_arguments)
  192.         {case 0:    ymin=actual_ymin;
  193.         case 1:        ymax=actual_ymax;
  194.         case 2:        ;
  195.         case 3:        ;
  196.         default:    ;
  197.         }
  198.     last=i-1;
  199.     if(transposing)
  200.         {i=logx; logx=logy; logy=i;
  201.         i=x_arguments; x_arguments=y_arguments; y_arguments=i;
  202.         pd=x; x=y; y=pd;
  203.         d=xmin; xmin=ymin; ymin=d;
  204.         d=xmax; xmax=ymax; ymax=d;
  205.         d=xdel; xdel=ydel; ydel=d;
  206.         }
  207. }
  208.  
  209. image()
  210. {    int i, j, k, st, segment;
  211.     
  212.     for(segment=i=0; i<=last; segment++)
  213.         {j=style[segment];
  214.         if(j>0)
  215.             {if(st=j%10) st--;
  216.             set_linestyle(st); j/=10;
  217.             set_color(max_color-j%10); j/=10;
  218.             set_linewidth(j);
  219.             move_abs_2(x[i],y[i]);
  220.             markers=0;
  221.             }
  222.         else
  223.             {set_marker_symbol(j ? -j : 6);
  224.             k=max_color-(-j)/10;
  225.             set_color(j ? k : max_color);
  226.             markers=1;
  227.             }
  228.         while(i<=last)
  229.             {if(markers)marker_abs_2(x[i],y[i]);
  230.             else line_abs_2(x[i],y[i]);
  231.             if(i++ ==p_data[segment])
  232.                 {text(p_text[segment]);
  233.                 if(breaking) break;
  234.                 else segment++;
  235.                 }
  236.             else if(default_labeling) text(default_label);
  237.             }
  238.         }
  239.     set_linewidth(1);
  240.     set_linestyle(0);
  241.     set_color(7);
  242. }
  243.  
  244. /* get_parameter - process one command line option
  245.         (return # parameters used) */
  246. get_parameter(argc,argv) int argc; char **argv;
  247. {    int i;
  248.     if(streq(*argv,"-a"))
  249.         {i=axis_arg(argc,argv,&abscissa_step,&abscissa,&i);
  250.         abscissa_arguments=i-1;
  251.         automatic_abscissas=1;
  252.         return i;
  253.         }
  254.     else if(streq(*argv,"-b")) {breaking=1; return 1;}
  255.     else if(streq(*argv,"-c"))
  256.         {if(argc>1) {default_labeling=1; default_label=argv[1]; return 2;}
  257.         else gripe_arg(argv[0]);
  258.         }
  259.     else if(streq(*argv,"-d")) {debugging=1; return 1;}
  260.     else if(streq(*argv,"-g"))
  261.         {if(argc>1 && numeric(argv[1]))
  262.             {grid_style=atoi(argv[1]); return 2;
  263.             }
  264.         else gripe_arg(argv[0]);
  265.         }
  266.     else if(streq(*argv,"-h"))
  267.         {if(argc>1 && numeric(argv[1]))
  268.             {height_used=atof(argv[1]); return 2;
  269.             }
  270.         else gripe_arg(argv[0]);
  271.         }
  272.     else if(streq(*argv,"-l"))
  273.         {if(argc>1) {text_labeling=1; text_label=argv[1]; return 2;}
  274.         else gripe_arg(argv[0]);
  275.         }
  276.     else if(streq(*argv,"-r"))
  277.         {if(argc>1 && numeric(argv[1]))
  278.             {right_move=atof(argv[1]); return 2;
  279.             }
  280.         else gripe_arg(argv[0]);
  281.         }
  282.     else if(streq(*argv,"-t")) {transposing=1; return 1;}
  283.     else if(streq(*argv,"-u"))
  284.         {if(argc>1 && numeric(argv[1]))
  285.             {up_move=atof(argv[1]); return 2;
  286.             }
  287.         else gripe_arg(argv[0]);
  288.         }
  289.     else if(streq(*argv,"-w"))
  290.         {if(argc>1 && numeric(argv[1]))
  291.             {width_used=atof(argv[1]); return 2;
  292.             }
  293.         else gripe_arg(argv[0]);
  294.         }
  295.     else if(streq(*argv,"-n")) {numeric_labeling=0; return 1;}
  296.     else if(streq(*argv,"-m"))
  297.         {i=1;
  298.         while((argc>i) && numeric(argv[i]) && i<=MAXSTYLES)
  299.             {style[i-1]=atoi(argv[i]); i++;}
  300.         return i;
  301.         }
  302.     else if(streq(*argv,"-x"))
  303.         {i=axis_arg(argc,argv,&xmin,&xmax,&xdel);
  304.         x_arguments=i-1;
  305.         return i;
  306.         }
  307.     else if(streq(*argv,"-y"))
  308.         {i=axis_arg(argc,argv,&ymin,&ymax,&ydel);
  309.         y_arguments=i-1;
  310.         return i;
  311.         }
  312.     else if(streq(*argv,"-xl"))
  313.         {i=axis_arg(argc,argv,&xmin,&xmax,&xdel);
  314.         x_arguments=i-1;
  315. /*        printf("before taking log: xmin=%f, xmax=%f, xdel=%f \n",
  316.         xmin,xmax,xdel);
  317. */
  318.         if(i>1) take_log(&xmin);
  319.         if(i>2) take_log(&xmax);
  320.         if(i>3) take_log(&xdel);
  321. /*        printf("after taking log: xmin=%f, xmax=%f, xdel=%f \n",
  322.         xmin,xmax,xdel);
  323. */
  324.         logx=1;
  325.         return i;
  326.         }
  327.     else if(streq(*argv,"-yl"))
  328.         {i=axis_arg(argc,argv,&ymin,&ymax,&ydel);
  329.         y_arguments=i-1;
  330.         logy=1;
  331.         if(i>1) take_log(&ymin);
  332.         if(i>2) take_log(&ymax);
  333.         if(i>3) take_log(&ydel);
  334.         return i;
  335.         }
  336.     else gripe(argv);
  337. }
  338.  
  339. axis_arg(argc,argv,qmin,qmax,qdel)
  340. int argc; char **argv; double *qmin,*qmax,*qdel;
  341. {    int i=1;
  342.     if((argc>i) && numeric(argv[i])) *qmin=atof(argv[i++]);
  343.     if((argc>i) && numeric(argv[i])) *qmax=atof(argv[i++]);
  344.     if((argc>i) && numeric(argv[i])) *qdel=atof(argv[i++]);
  345.     return i;
  346. }
  347.  
  348. int streq(a,b) char *a,*b;
  349. {    while(*a)
  350.         {if(*a!=*b)return 0;
  351.         a++; b++;
  352.         }
  353.     return 1;
  354. }
  355.  
  356. gripe_arg(s) char *s;
  357. {    printf("argument missing for switch %s",s);
  358.     help();
  359. }
  360.  
  361. gripe_negative()
  362. {    puts("nonpositive value along logrithmic axis ");
  363.     exit();
  364. }
  365.  
  366. gripe(argv) char **argv;
  367. {    puts(*argv); puts(" isn\'t a legal argument \n\n");
  368.     help();
  369. }
  370.  
  371. help()
  372. {    puts("sample usage...      graph  [data_file] [options]\n");
  373.     puts("options are:\n");
  374.     puts("  -a  [step [start]] automatic abscissas \n");
  375.     puts("  -b                 break graph after each label \n");
  376.     puts("  -c  <text>         default label for points \n");
  377.     puts("  -g                 grid style: 0=none 1=frame 2=full \n");
  378.     puts("  -h  <num>          fraction of screen height to use\n");
  379.     puts("  -r  <num>          fraction of screen to move right before plotting\n");
  380.     puts("  -l  <text>         label for graph \n");
  381.     puts("  -m  n1 n2 n3...    ni=0 for markers or nonzero for line styles: \n");
  382.     puts("                     ni=WCS, where W=width, C=color, S=dash style \n");
  383.     puts("  -n                 omit numbers on axes \n");
  384.     puts("  -t                 transpose x & y \n");
  385.     puts("  -u  <num>          fraction of screen to move up before plotting\n");
  386.     puts("  -w  <num>          fraction of screen width to use\n");
  387.     puts("  -x[l]  [min [max]]  l signals log axis,\n");
  388.     puts("                      x axis extends from min to max \n");
  389.     puts("  -y[l]  [min [max]]  similar for y axis\n\n");
  390.     printf("Version %s for %s \n",VERSION,machine);
  391.     puts(RIGHT);
  392.     exit();
  393. }
  394.  
  395. numeric(s) char *s;
  396. {    char c;
  397.     while(c=*s++)
  398.         {if((c<='9' && c>='0') || c=='+' || c=='-' || c=='.') continue;
  399.         return 0;
  400.         }
  401.     return 1;
  402. }
  403.  
  404. take_log(q) double *q;
  405. {    if(*q>0.) *q=log10(*q);
  406.     else {printf("nonpositive argument %f for log axis",*q); exit();}
  407. }
  408.