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

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