home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / DOTS151.ZIP / DOTS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-10  |  20.2 KB  |  746 lines

  1. /*    view - view a synthetic object in 3D
  2.  
  3.     history...
  4.         8 Oct 90    1.51: Extra new_frame removed, so PostScript
  5.                     output works.  '+' and '-' also change amount
  6.                     of enlargement or shrinking.  Hitting any key
  7.                     interrupts the current display.
  8.         4 Aug 90    1.50: Help display is now properly centered.
  9.                     Final viewpoint is printed when program finishes.
  10.                     pgup and pgdn move observer in and out.
  11.                     Hard copy versions accept configuration files,
  12.                     and no longer require the user to type 'Q'.
  13.         11 Aug 88    1.44: clipping at box surface
  14.         17 Jun 88    1.43: improved help page, fixed index bug, general
  15.                     code cleanup.
  16.         29 Mar 88    1.42: Storing points as floats rather than doubles,
  17.                     enlarged arrays to 3000, specifying multiple
  18.                     linestyles implies -b.
  19.         29 Jun 87    Can initialize observer location
  20.         13 Apr 87    Multiple linestyles/markerstyles, breaking
  21.     -- v 1.3  --
  22.         11 May 85    Allowing two-character cursor keys.
  23.         6 May 85    Always calling terminate_view_surface(1) before exit().
  24.     Obeying ^S ^X ^D ^E in addition to regular cursor keys.
  25.          18 Apr 85    Using cursor control keys defined in g.h.
  26. */
  27.  
  28. #include <stdio.h>
  29. #include <math.h>
  30. #include <string.h>
  31. #include <ctype.h>
  32. #include "g3.h"
  33. #include "g.h"
  34. #include "scr_ci.h"
  35.  
  36. char *malloc();
  37.  
  38. #define VERSION "1.51"
  39. #define RIGHT "Copyright (c) 1985, 1990 by James R. Van Zandt.  All rights reserved.\n"
  40. #define RESTRICTION "This program may be reproduced for personal, non-profit use only.\n"
  41.  
  42. #define d2r (3.1415926535/180.)
  43. #define ENTRIES 3000
  44. #define MAXLAB 200
  45. #define MAXSTYLES 50
  46. #define BUFSIZE 200
  47.  
  48. extern double best_width, best_height;
  49.  
  50. extern int debugging;
  51. char string[80];
  52. static char buf[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE];
  53. char *default_script_file = "";
  54. char *program_name = NULL;
  55. int style[MAXSTYLES];        /* array of requested line styles    */
  56. int repeat[MAXSTYLES];        /* array of repeat counts for line styles    */
  57. int persp=1,    /* nonzero if perspective projection desired */
  58. markers=0,        /* nonzero if marker desired at each data point */
  59. framing=1;        /* nonzero if frame desired around plot */
  60. int tails=0;
  61. int observer_viewpoint=0;
  62. int scaling=0;    /* nonzero if scaling data to fill a cube */
  63. int breaking=0;                /* nonzero if breaking (disconnecting) graph
  64.                                 after each label in input */
  65. int automatic_abscissas=0;    /* nonzero if abscissas are to be generated */
  66. int abscissa_arguments=0;    /* number specified: abscissa spacing & start */
  67. int logx=0;                    /* nonzero if x axis is to be logrithmic */
  68. int logy=0;                    /* nonzero if y axis is to be logrithmic */
  69. int logz=0;                    /* nonzero if z axis is to be logrithmic */
  70.  
  71. int x_arguments=0;            /* number specified: xmin, xmax, xdel    */
  72. int y_arguments=0;            /* number specified: ymin, ymax, ydel    */
  73. int z_arguments=0;            /* number specified: zmin, zmax, zdel    */
  74. int standard_input=0;        /* nonzero if data is coming from standard input */
  75. int labels=0;                /* number of user-supplied labels
  76.                                  (index into next two arrays) */
  77. int numstyles=0;            /* # linestyles specified by user */
  78. int p_data[MAXLAB]; char *p_text[MAXLAB];
  79. char null_label[]="";
  80.  
  81. static double cc, ss, angle, step, factor=1.,
  82.     enlarge=1.,            /* scale factor for display size */
  83.     growth=1.414,        /* factor for changing scale factor */
  84.     abscissa=0.,        /* default starting value for automatic abscissas */
  85.     abscissa_step=1.,    /* default step for automatic abscissas */
  86. p1=-3., p2=0., p3=0.,    /* observer location */
  87. ox, oy,                    /* screen coordinates of top left corner */
  88. diag,                    /* extent of viewable volume */
  89. data_size;                /* extent of data */
  90.  
  91. #define REAL float
  92.  
  93. REAL *x, *y, *z;
  94. double xmin, xmax, ymin, ymax, zmin, zmax;
  95. int last;
  96.  
  97. main(argc, argv) int argc; char **argv;
  98. {    int i, j;
  99.  
  100.     if(argc<2 || (argc>1 && streq(argv[1], "?"))) sample();
  101.     read_data(argc, argv);
  102.     
  103.     initialize_core(0,0,3);
  104.     select_view_surface(1);
  105.     initialize_view_surface(1);
  106.  
  107.     initialize_parameters(argc, argv);
  108.     while(1)
  109.         {if(!plotting_device)
  110.             new_frame();                /* clears the screen */
  111.         if(persp) perspective(p1, p2, p3);
  112.         else parallel(p1, p2, p3);
  113.         view_plane_normal(-p1, -p2, -p3);
  114.         create_temporary_segment(1); /* finds viewing transformation */
  115.         frame();            /* draw framework around image */
  116.         image();            /* use drawing primitives to create image */
  117.         close_temporary_segment();    
  118.         if(plotting_device) quit();
  119.         update_parameters();
  120.         }
  121. }
  122.  
  123. initialize_parameters(argc, argv) int argc; char **argv;
  124. {/*    if(want("use right handed coordinate system? ")) */
  125.         coordinate_system_type(1);        /* default coordinates are LH */
  126.     ndc_space_2(best_width, best_height); /* enable use of all of screen */
  127.     viewport2(0., best_width, 0., best_height); /* viewport is all of screen */
  128.     /*    if(want("enable clipping? ")) */
  129.         clip_window(1);
  130.     view_up_3(0., 0., 1.);        /* vector in this direction appears
  131.                                        vertical in final view        */
  132.     angle=3.14159/12.;
  133.     ss=sin(angle); cc=cos(angle);
  134. }
  135.  
  136. update_parameters()
  137. {    int c;
  138.     static double t;
  139.  
  140.     while(1)
  141.         {c=scr_ci();
  142.         switch(c)
  143.             {case '+':    angle *= 4.; step *= 4.; factor *= 4.;
  144.                         growth *= growth;
  145.                         growth *= growth;
  146.                         ss=sin(angle); cc=cos(angle);
  147.                         break;
  148.             case '-':    angle /= 4.; step /= 4.; factor /= 4.;
  149.                         growth = sqrt(sqrt(growth));
  150.                         ss=sin(angle); cc=cos(angle);
  151.                         break;
  152.             case '?':    help();    return;
  153.             case 'q':
  154.             case 'Q':    quit();
  155.             default:
  156.                 {c &= 0xff;
  157.                 if((c==up_char)|(c==('E'-64))) {p3+=step; return;}
  158.                 else if((c==down_char)|(c==('X'-64))) {p3-=step; return;}
  159.                 else if((c==right_char)|(c==('D'-64)))
  160.                     {t=cc*p1-ss*p2; p2= ss*p1+cc*p2; p1=t; return;
  161.                     }
  162.                 else if((c==left_char)|(c==('S'-64)))
  163.                     {t=cc*p1+ss*p2; p2=-ss*p1+cc*p2; p1=t; return;
  164.                     }
  165.                 else if(c == pgup_char)
  166.                     {if(!persp) goto BIGGER;
  167.                     p1/=growth; p2/=growth; p3/=growth; step/=growth; return;
  168.                     }
  169.                 else if(c == pgdn_char)
  170.                     {if(!persp) goto SMALLER;
  171.                     p1*=growth; p2*=growth; p3*=growth; step*=growth; return;
  172.                     }
  173.                 else if(c == home_char)
  174.                     {
  175. BIGGER:                enlarge *= growth;
  176.                     diag = data_size/enlarge;
  177.                     window(-diag*best_width, diag*best_width, 
  178.                            -diag*best_height, diag*best_height);
  179.                     ox=-diag*best_width; oy=diag*best_height*.95;
  180.                     return;
  181.                     }
  182.                 else if(c == end_char)
  183.                     {
  184. SMALLER:            enlarge /= growth;
  185.                     diag = data_size/enlarge;
  186.                     window(-diag*best_width, diag*best_width, 
  187.                            -diag*best_height, diag*best_height);
  188.                     ox=-diag*best_width; oy=diag*best_height*.95;
  189.                     return;
  190.                     }
  191.                         
  192. {
  193. FILE *dfile;
  194. dfile = fopen("debug","a");
  195. fprintf(dfile, "illegal character %d = %02xH\n", c, c);
  196. fclose(dfile);
  197. }                
  198.                 putchar(7);  /* beep */
  199.                 break;
  200.                 }
  201.             }
  202.         puts("\008 \008");    /* erase that character */
  203.         }
  204. }
  205.  
  206. quit()
  207. {
  208.     terminate_view_surface(1); 
  209.     printf("last viewpoint was (%f, %f, %f),\n", p1, p2, p3);
  210.     printf("scale factor %f\n", enlarge);
  211.     exit(0);
  212. }
  213.  
  214. char *msg[]={
  215. "            --- Status ---",
  216. "",
  217. buf,
  218. buf2,
  219. buf3,
  220. "",
  221. "",
  222. "            --- Key Commands ---",
  223. "",
  224. "cursor keys     move observer along a cylinder: higher, ",
  225. "                lower, around to left, or around to right.",
  226. "   pg up        move closer",
  227. "   pg dn        move back",
  228. "    home        enlarge",
  229. "    end         shrink",
  230. "     +          enlarge cursor key steps by a factor of 4",
  231. "     -          shrink cursor key steps by a factor of 4",
  232. "     Q          exit program",
  233. "",
  234. "     ?          print this help menu",
  235. "",
  236. "",
  237. "   <press any key to continue>",
  238. 0
  239. };
  240.  
  241. help()
  242. {    char **sp, c;
  243.     double x0, y0, z0, dz;
  244.     x0 = (xmax+xmin)/2.-diag*best_width;
  245.     z0 = (zmax+zmin)/2.+diag*best_height*.7;
  246.     dz = diag/24.;
  247.     new_frame();
  248.     parallel(0., -1., 0.);
  249.     view_plane_normal(0., 1., 0.);
  250.     create_temporary_segment(1); /* finds viewing transformation */
  251.     sprintf(buf,"current viewpoint is (%f, %f, %f)\n", p1, p2, p3);
  252.     sprintf(buf2,"                  or %3.2f degrees right of the x axis",
  253.         atan2(p2, p1)/d2r);
  254.     sprintf(buf3,
  255.         "current step sizes are %f and %3.2f degrees  (default * %3.2f)",
  256.         step, angle/d2r, factor);
  257.     for (sp=msg; *sp; sp++)
  258.         {move_abs_3(x0, 0., z0); z0-=dz;
  259.         text(*sp);
  260.         }
  261.     
  262.     c=tolower(scr_ci());
  263.     if(c == 'q') quit();
  264.  
  265.     close_temporary_segment();    
  266. }
  267.  
  268. read_data(argc, argv) int argc; char **argv;
  269. {    int i, n, length, skipping, ac;
  270.     FILE *ifile;
  271.     double xx, yy, zz, xscale, yscale, zscale;
  272.     double data_xmin, data_xmax, data_ymin, data_ymax, data_zmin, data_zmax;
  273.     char *t, *s, **av;
  274.  
  275.     sscanf("1.9","%lf",&xx);        /* workaround for bug in strtod() */
  276.  
  277.     data_xmin = data_ymin = data_zmin = 1.e100;
  278.     data_xmax = data_ymax = data_zmax = -1.e100;
  279.     x = (REAL *)malloc(ENTRIES*sizeof(REAL));
  280.     y = (REAL *)malloc(ENTRIES*sizeof(REAL));
  281.     z = (REAL *)malloc(ENTRIES*sizeof(REAL));
  282.     if(x==NULL || y==NULL || z==NULL) 
  283.         {puts("can\'t allocate buffer"); 
  284.         exit(1);
  285.         }
  286.     p_data[0]=-1;
  287.     argc--; argv++;
  288.       if(argc>=1 && **argv=='?') sample();
  289.     ac = argc; av = argv; argc = 0;
  290.     while(ac>0)
  291.         {
  292.         if(**av == '&')         /* device driver configuration file */
  293.             {config_file = (*av)+1;
  294.             ac--; av++;
  295.             }
  296.         else if(**av=='-')
  297.             {i=get_parameter(ac, av);
  298.             ac-=i; av+=i;
  299.             }
  300.         else {argv[argc++] = *av++; ac--;}
  301.         }
  302.     if(!plotting_device) 
  303.         printf("after data is plotted, type 'Q' to exit or '?' \
  304. for help display");
  305.     if(automatic_abscissas && abscissa_arguments==0 && x_arguments)
  306.         {abscissa = xmin;
  307.         }
  308.     i = 0;
  309.     while(1)
  310.         {if(argc>0)
  311.             {ifile=fopen(argv[0], "r");
  312.             if(ifile==0) {printf("file %s not found\n", argv[0]); exit(1);}
  313.             else
  314.                 {if(*default_script_file==0)
  315.                     {                /* construct default script file name */
  316.                     s = malloc(3+strlen(argv[0]));
  317.                     if(s)
  318.                         {default_script_file = s;
  319.                         strcpy(default_script_file, argv[0]);
  320.                         if(s = strchr(default_script_file, '.')) *s=0;
  321.                         strcat(default_script_file, ".f");
  322.                         }
  323.                     }
  324.                 }
  325.             }
  326.         else {ifile = stdin; standard_input++;}
  327.         argc--; argv++;
  328.         while(i<ENTRIES)
  329.             {if(fgets(buf, BUFSIZE, ifile)==0)
  330.                 {if(standard_input) 
  331.                     {fclose(ifile); 
  332.                     ifile=fopen("/dev/con", "r");
  333.                     }
  334.                 break;
  335.                 }
  336.             if(buf[0]==';') continue;    /* ignore comments */
  337.             t=buf+strlen(buf)-1;
  338.             while(t>buf && (*t=='\015' || *t=='\n')) *t--=0;
  339.             t=buf; while(*t && isspace(*t)) t++;
  340.             if(*t==0) continue;            /* ignore blank lines */
  341.             if(automatic_abscissas)
  342.                 {xx=abscissa;
  343.                 abscissa+=abscissa_step;
  344.                 sscanf(buf, "%lf %lf", &yy, &zz);
  345.                 }
  346.             else
  347.                 {sscanf(buf, "%lf %lf %lf", &xx, &yy, &zz);
  348.                 }
  349.             x[i]=xx; y[i]=yy; z[i]=zz;    /* convert to REAL */
  350.             s=buf;
  351.             skipping=3;
  352.             if(automatic_abscissas) skipping--;   
  353.             while(skipping--)
  354.                 {while(*s==' ')s++;                        /* skip a number */
  355.                 while(*s && (*s!=' '))s++;
  356.                 }
  357.             while(*s==' ')s++;
  358.             if((length=strlen(s))&&(labels<MAXLAB))
  359.                 {if(*s=='\"')
  360.                     {t=++s;
  361.                     while(*t && (*t!='\"')) t++;
  362.                     }
  363.                 else
  364.                     {t=s;
  365.                     while(*t && (*t!=' '))t++;
  366.                     }
  367.                 *t=0;
  368.                 length=t-s;
  369.                 p_data[labels]=i;
  370.                 p_text[labels]=(char *)malloc(length+1);
  371.                 if(p_text[labels]) strcpy(p_text[labels++], s);
  372.                 }
  373.             if(logx) {if(x[i]<=0.) gripe_negative(); x[i]=log10(x[i]);}
  374.             if(logy) {if(y[i]<=0.) gripe_negative(); y[i]=log10(y[i]);}
  375.             if(logz) {if(z[i]<=0.) gripe_negative(); z[i]=log10(z[i]);}
  376.             if(x[i]<data_xmin) data_xmin=x[i];
  377.             if(y[i]<data_ymin) data_ymin=y[i];
  378.             if(z[i]<data_zmin) data_zmin=z[i];
  379.     
  380.             if(x[i]>data_xmax) data_xmax=x[i];
  381.             if(y[i]>data_ymax) data_ymax=y[i];
  382.             if(z[i]>data_zmax) data_zmax=z[i];
  383.             if(labels==MAXLAB) break;
  384.             i++;
  385.             }
  386.         if(argc<=0) break;
  387.         breaking=1;
  388.         if(labels && (p_data[labels-1]==i-1)) continue;
  389.         p_data[labels]=i-1;
  390.         p_text[labels++]= null_label;
  391.         }
  392.     switch(x_arguments)
  393.         {case 0:    xmin=data_xmin;
  394.         case 1:        xmax=data_xmax;
  395.         case 2:        ;
  396.         case 3:        ;
  397.         default:    ;
  398.         }
  399.     switch(y_arguments)
  400.         {case 0:    ymin=data_ymin;
  401.         case 1:        ymax=data_ymax;
  402.         case 2:        ;
  403.         case 3:        ;
  404.         default:    ;
  405.         }
  406.     switch(z_arguments)
  407.         {case 0:    zmin=data_zmin;
  408.         case 1:        zmax=data_zmax;
  409.         case 2:        ;
  410.         case 3:        ;
  411.         default:    ;
  412.         }
  413.     xx=xmax-xmin; yy=ymax-ymin; zz=zmax-zmin;
  414.     if(scaling)
  415.         {n=i;
  416.         xscale=1./xx; yscale=1./yy; zscale=1./zz;
  417.         for (i=0; i<n; i++) {x[i]*=xscale; y[i]*=yscale; z[i]*=zscale;}
  418.         xmin*=xscale; ymin*=yscale; zmin*=zscale;
  419.         xmax*=xscale; ymax*=yscale; zmax*=zscale;
  420.         xx=yy=zz=1.;
  421.         }
  422.     data_size=sqrt(xx*xx+yy*yy+zz*zz)/2./best_height;
  423.     diag=data_size/enlarge;
  424.     view_reference_point((xmax+xmin)/2., (ymin+ymax)/2., (zmin+zmax)/2.);
  425.     window(-diag*best_width, diag*best_width, 
  426.            -diag*best_height, diag*best_height); /* use all of view surface */
  427.     ox=-diag*best_width; oy=diag*best_height*.95;
  428.     step=diag;    
  429.     switch(observer_viewpoint)
  430.         {default:    p1=2.*step; 
  431.         case 1:        p2=-2.*sqrt(3.)*step; 
  432.         case 2:        p3=step;
  433.         case 3:        ;
  434.         }        
  435.     last=i-1;
  436.     if(last<=0)
  437.         {puts("no data points found \n");
  438.         sample();
  439.         }
  440. /*    printf("x in (%f, %f), \ny in (%f, %f), \nz in (%f, %f) \n", xmin, xmax,
  441.     ymin, ymax, zmin, zmax);
  442.     printf("xx, yy, zz=(%f,%f,%f), diag=%f, step=%f \n",xx, yy, zz, diag, step);
  443.     printf("points 0 through %d \n", last); getchar();
  444. */
  445. }
  446.  
  447. char *sample_msg[]={
  448. "display 3D vector graphics\n",
  449. "sample usage:   dots  alpha.dat  [options]\n",
  450. "options are:\n",
  451. "   -a [step [start]] automatic abscissas \n",
  452. "   -b     break graph after each label\n",
  453. "   -f     omit frame around plot \n",
  454. "   -m  n1 n2 n3...    n positive for line styles: n = WCS, \n",
  455. "                      where W=width, C=color, S=dash style,\n",
  456. "                      or n = -CS for markers \n",
  457. "   -o  ox oy oz       specify initial observer location\n",
  458. "   -p     use parallel rather than perspective projection\n",
  459. "   -s     scale data to fill a cube\n",
  460. "   -s  num            enlarge display by factor num\n",
  461. "   -t     draw line from each data point to the XY plane\n",
  462. "   -x  NUM1 NUM2      let x axis extend from NUM1 to NUM2\n",
  463. "   -y  NUM1 NUM2      let y axis extend from NUM1 to NUM2\n",
  464. "   -z  NUM1 NUM2      let z axis extend from NUM1 to NUM2\n\n",
  465. RIGHT,
  466. RESTRICTION,
  467. 0};
  468.  
  469. sample()
  470. {    char **sp;
  471.     printf("DOTS   version %s, interface %s for %s \n",
  472.     VERSION, interface_version, machine);
  473.     for (sp=sample_msg; *sp; sp++) printf(*sp);
  474.     exit(0);
  475. }
  476.  
  477. /* get_parameter - process one command line option
  478.         (return # parameters used) */
  479. get_parameter(argc, argv) int argc; char **argv;
  480. {    int i;
  481.     double junk;
  482.     char *s;
  483.  
  484.     if(streq(*argv, "-x"))
  485.         {
  486. /*
  487.         if(argc<3) gripe(argv);
  488.         xmin=atof(argv[1]); xmax=atof(argv[2]); x_arguments=2; return 3;
  489. */
  490.         i=get_double(argc, argv, 2, &xmin, &xmax, &xmax);
  491.         x_arguments=i-1;
  492.         return i;
  493.         }
  494.     else if(streq(*argv, "-y"))
  495.         {
  496. /*
  497.         if(argc<3) gripe(argv);
  498.         ymin=atof(argv[1]); ymax=atof(argv[2]); return 3;
  499. */
  500.         i=get_double(argc, argv, 2, &ymin, &ymax, &ymax);
  501.         y_arguments=i-1;
  502.         return i;
  503.         }
  504.     else if(streq(*argv, "-z"))
  505.         {
  506. /*
  507.         if(argc<3) gripe(argv);
  508.         zmin=atof(argv[1]); zmax=atof(argv[2]); return 3;
  509. */
  510.         i=get_double(argc, argv, 2, &zmin, &zmax, &zmax);
  511.         z_arguments=i-1;
  512.         return i;
  513.         }
  514.     else if(streq(*argv, "-a"))
  515.         {i=get_double(argc, argv, 2, &abscissa_step, &abscissa, &abscissa);
  516.         abscissa_arguments=i-1;
  517.         automatic_abscissas=1;
  518.         return i;
  519.         }
  520.     else if(streq(*argv, "-b")) {breaking=1; return 1;}
  521.     else if(streq(*argv, "-d")) {debugging=1; return 1;}
  522.     else if(streq(*argv, "-f")) {framing=0; return 1;}
  523.     else if(streq(*argv,"-m"))
  524.         {numstyles=0;
  525.         if(argc>1 && hexanumeric(argv[1]))
  526.             {i=1;
  527.             while((--argc >0) && hexanumeric(argv[1]) && numstyles<MAXSTYLES)
  528.                 {if(s=strchr(*++argv,'*'))
  529.                     {repeat[numstyles]=atoi(*argv);
  530.                     s++;
  531.                     }
  532.                 else {repeat[numstyles]=1; s=*argv;}
  533.                 style[numstyles++]=atox(s);
  534.                 i++;
  535.                 }
  536.             if(numstyles>1 || repeat[0]>1) breaking=1;
  537.             return i;
  538.             }
  539.         else 
  540.             {markers=1; return 1;
  541.             }
  542.         }
  543.     else if(streq(*argv, "-o"))
  544.         {i=get_double(argc, argv, 3, &p1, &p2, &p3);
  545.         observer_viewpoint=i-1;
  546.         return i;
  547.         }
  548.     else if(streq(*argv, "-p")) {persp=0; return 1;}
  549.     else if(streq(*argv, "-s")) 
  550.         {i = get_double(argc, argv, 1, &enlarge, &enlarge, &enlarge);
  551.         if(enlarge <= 0.) enlarge = 1.;
  552.         if(i < 2) scaling = 1;
  553.         return i;
  554.         }
  555.     else if(streq(*argv, "-t")) {tails=1; return 1;}
  556.     else gripe(argv);
  557. }
  558.  
  559. atox(s) char *s;
  560. {    int n, c, sign;
  561.     while(*s==' '||*s=='\t') s++;
  562.     if(*s=='-')
  563.         {sign=1;
  564.         s++;
  565.         }
  566.     else sign=0;
  567.     n=0;
  568.     while(1)
  569.         {c=*s++;
  570.         if(c>='0' && c<='9') c-='0';
  571.         else
  572.             {if(c>='a') c-=0x20;        /* convert to upper case */
  573.             if(c>='A' && c<='F') c=c-'A'+10;
  574.             else return (sign?-n:n);
  575.             }
  576.         n=(n<<4)+c;
  577.         }
  578. }
  579. get_double(argc, argv, permitted, a, b, c)
  580. int argc, permitted; char **argv; double *a, *b, *c;
  581. {    int i=1;
  582.     if((permitted--)>0 && (argc>i) && numeric(argv[i])) *a=atof(argv[i++]);
  583.     if((permitted--)>0 && (argc>i) && numeric(argv[i])) *b=atof(argv[i++]);
  584.     if((permitted--)>0 && (argc>i) && numeric(argv[i])) *c=atof(argv[i++]);
  585.     return i;
  586. }
  587.  
  588. numeric(s) char *s;
  589. {    char c;
  590.     while(c=*s++)
  591.         {if((c<='9' && c>='0') || c=='e' || c=='E' || 
  592.             c=='+' || c=='-' || c=='.') continue;
  593.         return 0;
  594.         }
  595.     return 1;
  596. }
  597.  
  598. hexanumeric(s) char *s;
  599. {    char c; 
  600.     int numeral_found=0;
  601.     if(numeric(s)) return 1;
  602.     while(c=*s++)
  603.         {c=toupper(c);
  604.         if((c<='9' && c>='0') || (c<='F' && c>='A')) 
  605.             {numeral_found=1; continue;
  606.             }
  607.         else if(strchr("*-", c)) continue;
  608.         return 0;
  609.         }
  610.     return numeral_found;
  611. }
  612.  
  613. int streq(a, b) char *a, *b;
  614. {    while(*a)
  615.         {if(*a!=*b)return 0;
  616.         a++; b++;
  617.         }
  618.     return 1;
  619. }
  620.  
  621. gripe_negative()
  622. {    puts("nonpositive value along logrithmic axis ");
  623.     exit(1);
  624. }
  625.  
  626. gripe(argv) char **argv;
  627. {    puts(*argv); puts(" isn\'t a legal argument \n");
  628.     sample();
  629. }
  630.  
  631. frame()
  632. {    double xx, yy, zz;
  633.  
  634.                             /* draw axes */
  635.     set_color(1);
  636.     if((xmin<=0.)&&(xmax>=0.)) xx=0.; else xx=xmin;
  637.     if((ymin<=0.)&&(ymax>=0.)) yy=0.; else yy=ymin;
  638.     if((zmin<=0.)&&(zmax>=0.)) zz=0.; else zz=zmin;
  639.     move_abs_3(xmin, yy, zz); line_abs_3(xmax, yy, zz); text("x");
  640.     move_abs_3(xx, ymin, zz); line_abs_3(xx, ymax, zz); text("y");
  641.     move_abs_3(xx, yy, zmin); line_abs_3(xx, yy, zmax); text("z");
  642.  
  643.     if(!framing) return;
  644.  
  645.                             /* draw frame */
  646.     set_color(5);
  647.     move_abs_3(xmin, ymin, zmin);
  648.     line_abs_3(xmax, ymin, zmin);
  649.     line_abs_3(xmax, ymax, zmin);
  650.     line_abs_3(xmin, ymax, zmin);
  651.     line_abs_3(xmin, ymin, zmin);
  652.     
  653.     line_abs_3(xmin, ymin, zmax);
  654.  
  655.     line_abs_3(xmax, ymin, zmax);
  656.     line_abs_3(xmax, ymin, zmin);
  657.     line_abs_3(xmax, ymin, zmax);
  658.  
  659.     line_abs_3(xmax, ymax, zmax);
  660.     line_abs_3(xmax, ymax, zmin);
  661.     line_abs_3(xmax, ymax, zmax);
  662.  
  663.     line_abs_3(xmin, ymax, zmax);
  664.     line_abs_3(xmin, ymax, zmin);
  665.     line_abs_3(xmin, ymax, zmax);
  666.  
  667.     line_abs_3(xmin, ymin, zmax);
  668.  
  669. }
  670.  
  671. image()
  672. {    int i, j, j_style=1, k, st, group, segment, n;
  673.  
  674.     for(segment=group=i=0; i<=last; group++)
  675.         {if(!plotting_device && kbhit()) break;
  676.         if(group<numstyles) {j_style=style[group]; n=repeat[group];}
  677.         else n=1;
  678.         while(n--)
  679.             {
  680.             j=j_style;
  681.             if(j>0)
  682.                 {if(st=j%16) st--;
  683.                 set_linestyle(st); j/=16;
  684.                 set_color(j%16); j/=16;
  685.                 set_linewidth(j);
  686.                 move_abs_3(x[i],y[i],z[i]);
  687.                 markers=0;
  688.                 }
  689.             else
  690.                 {j=-j;
  691.                 st=j%16;
  692.                 set_marker_symbol(st ? st : 6);
  693.                 j/=16;
  694.                 k=j%16;
  695.                 set_color(j ? k : 0);
  696.                 markers=1;
  697.                 }
  698.             while(i<=last)
  699.                 {if(xmin<=x[i] && x[i]<=xmax &&
  700.                     ymin<=y[i] && y[i]<=ymax &&
  701.                     zmin<=z[i] && z[i]<=zmax)    
  702.                     {if(markers)
  703.                         marker_abs_3(x[i],y[i], z[i]);
  704.                     else line_abs_3(x[i],y[i], z[i]);
  705.                     if(tails)
  706.                         {line_abs_3(x[i], y[i], 0.);
  707.                         if(i && (markers == 0))
  708.                             line_abs_3(x[i-1], y[i-1], 0.);
  709.                         move_abs_3(x[i], y[i], z[i]);
  710.                         }
  711.                     if(i++ == p_data[segment])
  712.                         {text(p_text[segment]);
  713.                         if(breaking) break;
  714.                         else {segment++; move_abs_3(x[i-1],y[i-1], z[i-1]);}
  715.                         }
  716.                     }
  717.                 else /* point not visible */
  718.                     {
  719.                     if(i++ != p_data[segment])
  720.                         {segment--;    /* compensate for later increment */
  721.                         n++;
  722.                         }
  723.                     break;            /* force a line break */
  724.                     }
  725.                 }
  726.             segment++;
  727.             }
  728.         }
  729.     set_linewidth(1);
  730.     set_linestyle(0);
  731.     set_color(0);
  732. }
  733.  
  734. want(s) char *s;
  735. {    printf(s);
  736.     scanf("%s", &string);
  737.     if((string[0]=='y')|(string[0]=='Y'))return 1;
  738.     else return 0;
  739. }
  740.  
  741. goodbye()
  742. {    printf("\n<press any key to continue>"); (void)getchar();
  743.     terminate_view_surface(1);
  744.     exit(0);
  745. }
  746.