home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / d / dots151.zip / GRAPHSRC.ZIP / G32.C < prev    next >
C/C++ Source or Header  |  1990-07-07  |  30KB  |  829 lines

  1. /*
  2.     g3 - three dimensional graphics interface
  3.  
  4.     history...
  5.         24 Mar 90    Added function prototypes
  6.         29 Oct 87    Scaling marker symbols by the pen diameter.
  7.         28 Oct 87    In polymarker_*_*, drawing n markers rather than
  8.                     n-1.  In polymarker_rel_2, saving current position
  9.                     and using marker_abs_2 rather than marker_rel_2.
  10.         16 Jun 87    For a wide line, displacing pen by pen_diameter on 
  11.                     each pass.  If pen_diameter is greater than 1, a
  12.                     stroke is added across each end to square it off.
  13.         16 May 87    Hid debugging code behind #ifdef's.
  14.                     Corrected aspect ratio scaling of marker symbols.
  15.         5 May 87    Using hardware for wide lines, if available.
  16.         24 Apr 86    If not widening, clipping first.  Using hardware for
  17.     dashed lines, if available.
  18.         19 Apr 86    Not displaying empty labels.
  19.         2 Dec 85    Using new gotoxy() call sequence.
  20.         6 May 85    Added rudimentary text().
  21.         27 Apr 85    Not using iline(). changed from maybe_dashed, etc. to
  22.     after_line, etc. so line routines could be executed in any order required.
  23.         18 Apr 85    different line widths and styles implemented.
  24.         7 Apr 85    Added linewidth and linestyle stubs.
  25.         9 Mar 85    hid (*erase_line)() references behind #ifdef's. changed
  26.     init() references to init_graphics(), removed inquire_current_color().
  27.         15 Feb 85    iwline() installed - draws wide lines.
  28. */
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32. #ifdef __TURBOC__
  33. #include <ctype.h>
  34. #endif
  35.  
  36. #include "g.h"
  37. #include "g3.h"
  38.  
  39. #ifdef DEBUG
  40. int textymin=400;
  41. int textymax=-400;
  42. #endif
  43.  
  44.                     /* integer line drawing routines */
  45. static int
  46.     icline(int a1, int a2, int b1, int b2),
  47.     idline(int a1, int a2, int b1, int b2),
  48.     iwline(int a1, int a2, int b1, int b2);
  49. static int clip( double *a, double *b, double *c );
  50. int (*after_line)(int a1, int a2, int b1, int b2);
  51.                     /* pointer to the line routine to follow line_abs_3() */
  52.  
  53. /*        variables        */
  54.  
  55. extern int debugging;
  56.  
  57. static int
  58.                         /* pointer to the line routine to follow icline()    */
  59. (*after_clip)(int a1, int a2, int b1, int b2),
  60.                         /* pointer to the line routine to follow iwline()    */
  61. (*after_wide)(int a1, int a2, int b1, int b2),
  62.                         /* pointer to the line routine to follow idline()    */
  63. (*after_dashed)(int a1, int a2, int b1, int b2),
  64. aspect,                /* 10*pixel height/pixel width                        */
  65. current_linewidth,    /* width of line (units of pixel height)            */
  66. current_linestyle=SOLID, /* style of line                                */
  67. current_x, current_y,        /* current position (integer)                */
  68. marker_symbol=1,    /* current marker symbol                            */
  69. scaled=0,            /* nonzero after markers have been rescaled            */
  70.  
  71. #define MAX_STYLE 9
  72. #define DASHES 8
  73. styles[MAX_STYLE*DASHES]={     /* 0 - solid         */
  74.     5,8,5,8,5,8,5,8,         /* 1 - dashed            */
  75.     5,3,5,3,5,3,5,3,        /* 2 - short dashes      */
  76.     4,1,4,1,4,1,4,1,         /* 3 - dotted            */
  77.     4,8,4,1,4,8,4,1,         /* 4 - dash-dot          */
  78.     4,9,4,1,4,1,0,0,         /* 5 - dash-dot-dot      */
  79.     4,10,4,1,4,1,4,1,         /* 6 - dash-dot-dot-dot  */
  80.     4,10,4,10,4,1,0,0,         /* 7 - dash-dash-dot     */
  81.     4,10,4,10,4,1,4,1,         /* 8 - dash-dash-dot-dot */
  82.     10,15,10,15,10,15},        /* 9 - dashed            */
  83. style_array[DASHES],/* array of currently used dash lengths
  84.                         in units of 1/8 pixel width                        */
  85. style_index=0,        /* index into style_array[]                            */
  86. step=12,            /* amount of current dash not yet drawn                */
  87. using_dash_hardware=0,    /* nonzero if linestyles implemented in 
  88.                        hardware and we can use them (not widening)        */
  89. reversed=0;            /* nonzero if endpoints of line have
  90.                         been swapped by icline()                        */
  91.  
  92. extern int
  93. clipping,            /* nonzero if clipping is enabled                    */
  94. front_clipping,        /* nonzero if front clipping is enabled */
  95. back_clipping,        /* nonzero if back clipping is enabled */
  96. graphics_level,        /* level of CORE graphics requested                    */
  97. initialized,        /* nonzero after output driver is initialized       */
  98. need_depth,            /* nonzero if depth must be calculated (perspective
  99.                         projection or depth clipping)                    */
  100. num_segments,        /* number of segments that still exist                */
  101. persp_proj,            /* nonzero if perspective projection requested        */
  102. segment_open,        /* nonzero if a segment is open                        */
  103. wmin1,wmax1,        /* minimum & maximum x values in device coordinates */
  104. wmin2,wmax2;        /* minimum & maximum y values in device coordinates */
  105.  
  106. extern double
  107. aspect_ratio,        /* height/width ratio of display                    */
  108. left_handed,        /* 1 for LH world coordinate system, -1 for RH        */
  109. vdist,                /* distance from viewpoint along view plane normal to
  110.                             viewplane                                    */
  111. c_bottom[4],c_top[4],    /* clip vectors...if x is visible, then            */
  112. c_left[4],c_right[4],    /* x[0]*c[0] + x[1]*c[1] + x[2]*c[2] > c[3]        */
  113. c_near[4],c_far[4],        /* for c equal to each of these six arrays        */
  114. /* cur_x, cur_y, cur_z,    current position (world coordinates) (in g3.h) */
  115. uu, vv, nn,                /* current position (viewport coordinates) */
  116. norm1, norm2, norm3,    /* view plane normal */
  117. p1, p2, p3,                /* direction for parallel projection, or
  118.                                     center of projection */
  119. up1, up2, up3,            /* view up vector */
  120. vrp1, vrp2, vrp3,        /* view reference point */
  121.  
  122. umin, umax,                /* window in world coordinates */
  123. vmin, vmax,
  124. wmin, wmax,
  125. vp_xmin, vp_xmax,        /* requested viewport in NDC */
  126. vp_ymin, vp_ymax,
  127. vp_zmin, vp_zmax,
  128. ndc_width, ndc_height, ndc_depth,    /* requested limits on NDC values */
  129. rot11, rot12, rot13, rot14,     /* rotation & projection matrix */
  130. rot21, rot22, rot23, rot24,
  131. rot31, rot32, rot33, rot34;  /* (3rd row is for perspective projections) */
  132.  
  133. /*        CORE graphics routines        */
  134.  
  135. double charwidth, charheight;
  136. double dx_plane, dy_plane, dz_plane;
  137. double dx_charup, dy_charup, dz_charup;
  138. int charpath, charjust, charprecision;
  139. double charspace=0.;
  140.  
  141. /*    inquire character attributes */
  142.  
  143. inquire_charsize(cw,ch)     double *cw,*ch;                           /**/
  144. {*cw=charwidth; *ch=charheight;
  145. }
  146.  
  147. inquire_charplane(dx,dy,dz) double *dx,*dy,*dz;                       /**/
  148. {*dx=dx_plane; *dy=dy_plane; *dz=dz_plane;
  149. }
  150.  
  151. inquire_charup_2(dx,dy) double *dx,*dy;                                  /**/
  152. {*dx=dx_charup; *dy=dy_charup;
  153. }
  154.  
  155. inquire_charup_3(dx,dy,dz)     double *dx,*dy,*dz;                          /**/
  156. {*dx=dx_charup; *dy=dy_charup; *dz=dz_charup;
  157. }
  158.  
  159. double    inquire_charspace()                        {return charspace;}                   /**/
  160. int        inquire_charpath()                         {return charpath;}                      /**/
  161. int        inquire_charjust()                        {return charjust;}                       /**/
  162. int        inquire_charprecision()                 {return charprecision;}              /**/
  163.  
  164. /*    inquire_current_position - report current position */
  165. inquire_current_position_2(x,y) double *x,*y; {*x=cur_x; *y=cur_y;}   /**/
  166. inquire_current_position_3(x,y,z) double *x,*y,*z;                    /**/
  167. {*x=cur_x; *y=cur_y; *z=cur_z;
  168. }
  169.  
  170. /*    inquire line parameters */
  171. inquire_linestyle(n) int *n; {return (*n=current_linestyle);}         /**/
  172. inquire_linewidth(n) int *n; {return (*n=current_linewidth);}         /**/
  173. inquire_marker_symbol(n) int *n; {return (*n=marker_symbol);}         /**/
  174.  
  175. /*    inquire viewing parameters */
  176. inquire_ndc_space_2(w,h) double *w,*h;                                /**/
  177. {    *w=ndc_width; *h=ndc_height;
  178. }
  179. inquire_ndc_space_3(w,h,d) double *w,*h,*d;                           /**/
  180. {    *w=ndc_width; *h=ndc_height; *d=ndc_depth;
  181. }
  182.  
  183. inquire_viewport_2(xmin,xmax,ymin,ymax)                               /**/
  184. double *xmin,*xmax,*ymin,*ymax;
  185. {    *xmin=vp_xmin; *xmax=vp_xmax;
  186.     *ymin=vp_ymin; *ymax=vp_ymax;
  187. }
  188.  
  189. inquire_viewport_3(xmin,xmax,ymin,ymax,zmin,zmax)                     /**/
  190. double *xmin,*xmax,*ymin,*ymax,*zmin,*zmax;
  191. {    *xmin=vp_xmin; *xmax=vp_xmax;
  192.     *ymin=vp_ymin; *ymax=vp_ymax;
  193.     *zmin=vp_zmin; *zmax=vp_zmax;
  194. }
  195.  
  196. inquire_window(x1,x2,y1,y2) double *x1,*x2,*y1,*y2;                   /**/
  197. {    *x1=umin; *x2=umax; *y1=vmin; *y2=vmax;}
  198.  
  199. inquire_open_temporary_segment() {return segment_open;}               /**/
  200.  
  201. /*    line - draw line from current position */
  202. line_abs_3(x,y,z) double x,y,z;                                       /**/
  203. {    static int previous_x,previous_y;
  204.     static double a[3],b[3];
  205. #ifdef TRACE
  206. {
  207. FILE *dfile;
  208. dfile = fopen("dfile","a");
  209. fprintf(dfile, "file %s line %3d: line_abs_3(%f,%f,%f)\n", __FILE__, __LINE__, x, y, z);
  210. fclose(dfile);
  211. }
  212. #endif /* TRACE */
  213.     reversed=0;
  214.     a[0]=uu; a[1]=vv; a[2]=nn; previous_x=current_x; previous_y=current_y;
  215.     move_abs_3(x,y,z);
  216.     b[0]=uu; b[1]=vv; b[2]=nn;
  217.     if(persp_proj)
  218.         {
  219. #ifdef DEBUG
  220.         /*if(debugging)
  221.             {printf("line (%10f,%10f,%10f) to (%10f,%10f,%10f)  \n",
  222.             a[0],a[1],a[2],b[0],b[1],b[2]);
  223.             } */
  224. #endif
  225.         if(front_clipping)
  226.             {if(clip(a,b,c_near)) return;
  227.             }
  228.         if(back_clipping)
  229.             {if(clip(a,b,c_far)) return;
  230.             }
  231.         else if((a[2]>0.)&&(b[2]>0.)) {}    /* can use integer clipping */
  232.         else if(clipping)
  233.             {/* clip along four planes */
  234.             if(clip(a,b,c_left)||clip(a,b,c_right )||
  235.                clip(a,b,c_top )||clip(a,b,c_bottom)  ) return;
  236.             if((a[2]<=0.)||(b[2]<=0.))return;
  237.             }
  238.         else return; /* one end invisible, clipping forbidden - omit line */
  239.         (*after_line)((int)(a[0]/a[2]),(int)(a[1]/a[2]),
  240.                       (int)(b[0]/b[2]),(int)(b[1]/b[2]));
  241.         }
  242.     else        /* parallel projection */
  243.         {if(front_clipping||back_clipping)
  244.             {if((front_clipping&&clip(a,b,c_near))||
  245.                  (back_clipping&&clip(a,b,c_far))) return;
  246.             (*after_line)((int)a[0],(int)a[1],(int)b[0],(int)b[1]);
  247.             }
  248.         else (*after_line)(previous_x,previous_y,current_x,current_y);
  249.         }
  250. }
  251.  
  252. /*    marker - display marker "n" */
  253. static int
  254. mark_index[]={0,1,3, 6,12,14, 19,24,28,32};
  255. static int xm[]=
  256. /*   x1 y1 x2 y2  ...for each line segment */
  257.     {00,00,00,00,                                            /* dot */
  258.     00,-20,00,20,    -40,00,40,00,                            /* plus */
  259.     -20,-18,20,18,   -20,18,20,-18, -40,00,40,00,            /* asterisk */
  260.  
  261.     -20,18,20,18,    20,18,40,00,   40,00,20,-18,             /* hexagon */ 
  262.     20,-18,-20,-18,  -20,-18,-40,00,  -40,00,-20,18,
  263.     -36,-18,36,18,   36,-18,-36,18,                            /* cross */
  264.     -36,0,-36,18,  -36,18,36,18,                            /* square */  
  265.     36,18,36,-18,  36,-18,-36,-18, -36,-18,-36,0,
  266.  
  267.     20,-10,40,00,    40,00,00,20,                           /* diamond */
  268.     00,20,-40,00,  -40,00,00,-20, 00,-20,20,-10,
  269.     00,-20,-40,-20, -40,-20,00,20,                  /* triangle, point up */ 
  270.     00,20,40,-20, 40,-20,00,-20, 
  271.     00,20,-40,20, -40,20,00,-20,                      /* triangle, point down */
  272.     00,-20,40,20, 40,20,00,20
  273.  
  274.     };
  275. #define MAX_MARKER_SYMBOL 9
  276.  
  277. marker_abs_3(x,y,z) double x,y,z;                                     /**/
  278. {    int i, j, resetting;
  279.     move_abs_3(x,y,z);
  280.     if(front_clipping) {if(nn<=wmin) return;}
  281.     if(back_clipping) {if(nn>wmax) return;}
  282.     if(persp_proj)
  283.         {if(nn<=0.) return;
  284.         current_x=(int)(uu/nn); current_y=(int)(vv/nn);
  285.         }
  286.     if(clipping)
  287.         {if((current_x<wmin1)||(current_x>wmax1)||
  288.             (current_y<wmin2)||(current_y>wmax2)  ) return;
  289.         }
  290.     j=mark_index[marker_symbol]*4;
  291. /*
  292. gotoxy(0,char_height); printf("x,y=%d,%d",current_x,current_y);
  293. gotoxy(0,2*char_height);
  294. i=mark_index[marker_symbol-1];
  295. printf("xm[%d...%d]=%d",i,j,xm[i]);
  296. for(i++ ;i<j; i++) printf(", %d",xm[i]);
  297. gotoxy(0,3*char_height);
  298. i=mark_index[marker_symbol-1];
  299. printf("ym[%d...%d]=%d",i,j,ym[i]);
  300. for(i++ ;i<j; i++) printf(", %d",ym[i]);
  301. */
  302.     resetting=0;
  303.     if(new_linestyle && 
  304.         current_linestyle!=SOLID && 
  305.         (current_linewidth==1 || new_linewidth)) 
  306.             {resetting=1;
  307.             (*new_linestyle)(SOLID);
  308.             }
  309.     for (i=mark_index[marker_symbol-1]*4; i<j; i+=4) 
  310.         {(*draw_line)(current_x+xm[i],  current_y+xm[i+1],
  311.                       current_x+xm[i+2],current_y+xm[i+3]);
  312.     if(resetting) reset_line();
  313. /* printf("\n*(draw_line)(%d,%d, %d,%d)",x1,y1,x2,y2); */
  314.         }
  315. }
  316.  
  317.  
  318. /*    move - move from current position */
  319. move_abs_3(x,y,z) double x,y,z;                                       /**/
  320. {    cur_x=x; cur_y=y; cur_z=z;
  321.     uu=rot11*x + rot12*y + rot13*z + rot14;
  322.     vv=rot21*x + rot22*y + rot23*z + rot24;
  323.     if(need_depth) {nn=rot31*x + rot32*y + rot33*z + rot34;}
  324.     if(!persp_proj) {current_x=(int)uu; current_y=(int)vv;}
  325. }
  326.  
  327. /*    ndc_space - define limits on normalized device coordinate values
  328.             w > h allows use of display device that's wider than it
  329.             is high. (w and h in range 0. to 1., either w or h must be 1.) */
  330. ndc_space_2(w,h) double w,h; {ndc_space_3(w,h,1.);}                   /**/
  331. ndc_space_3(w,h,d) double w,h,d;                                      /**/
  332. {    ndc_width=w;  if (vp_xmax>w) vp_xmax=w;
  333.     ndc_height=h; if (vp_ymax>h) vp_ymax=h;
  334.     ndc_depth=d;
  335. }
  336.  
  337. /*    new_frame - clear screen and redraw retained segments */
  338. new_frame() {clear_graphics();}                                       /**/
  339.  
  340. /*    parallel - define direction for parallel projection */
  341. parallel(x,y,z) double x,y,z;                                         /**/
  342. {    p1=x; p2=y; p3=left_handed*z; persp_proj=0;
  343.     need_depth=persp_proj||front_clipping||back_clipping;
  344. }
  345.  
  346. /*    perspective - define center of projection for perspective projection */
  347. perspective(x,y,z) double x,y,z;                                      /**/
  348. {    p1=x; p2=y; p3=left_handed*z; persp_proj=1;
  349.     need_depth=persp_proj||front_clipping||back_clipping;
  350. }
  351.  
  352. /*    polyline - draw lines connecting a series of points */
  353. polyline_abs_3(x,y,z,n) double *x,*y,*z; int n;                       /**/
  354. {    move_abs_3(*x++,*y++,*z++); while(--n)line_abs_3(*x++,*y++,*z++);
  355. }
  356. polyline_abs_2(x,y,n) double *x,*y; int n;                            /**/
  357. {    move_abs_2(*x++,*y++); while(--n)line_abs_2(*x++,*y++);
  358. }
  359. polyline_rel_3(x,y,z,n) double *x,*y,*z; int n;                       /**/
  360. {
  361.     move_rel_3(*x++,*y++,*z++);
  362.     while(--n)line_abs_3(*x++, *y++, *z++);
  363. }
  364. polyline_rel_2(x,y,n) double *x,*y; int n;                            /**/
  365. {
  366.     move_rel_2(*x++,*y++); while(--n)line_rel_2(*x++,*y++);
  367. }
  368.  
  369. /*    polygon - draw a polygon defined by its vertices */
  370. polygon_abs_3(x,y,z,n) double *x,*y,*z; int n;                        /**/
  371. {    double cx,cy,cz;
  372.     move_abs_3(*x++,*y++,*z++);
  373.     cx=cur_x; cy=cur_y; cz=cur_z;
  374.     while(--n)line_abs_3(*x++,*y++,*z++);
  375.     line_abs_3(cx,cy,cz);
  376. }
  377. polygon_abs_2(x,y,n) double *x,*y; int n;                             /**/
  378. {    double cx,cy;
  379.     move_abs_2(*x++,*y++); cx=cur_x; cy=cur_y;
  380.     while(--n)line_abs_2(*x++,*y++);
  381.     line_abs_2(cx,cy);
  382. }
  383. polygon_rel_3(x,y,z,n) double *x,*y,*z; int n;                        /**/
  384. {    double cx,cy,cz;
  385.     double sx,sy,sz;
  386.     cx=cur_x; cy=cur_y; cz=cur_z;
  387.     move_rel_3(*x++,*y++,*z++); sx=cur_x; sy=cur_y; sz=cur_z;
  388.     while(--n)line_abs_3(cx+ *x++,cy+ *y++,cz+ *z++);
  389.     line_abs_3(sx,sy,sz);
  390. }
  391. polygon_rel_2(x,y,n) double *x,*y; int n;                             /**/
  392. {    double sx,sy;
  393.     move_rel_2(*x++,*y++); sx=cur_x; sy=cur_y;
  394.     while(--n)line_rel_2(*x++, *y++);
  395.     line_abs_2(sx,sy);
  396. }
  397.  
  398. /*    polymarker - draw markers at a series of points */
  399. polymarker_abs_3(x,y,z,n) double *x,*y,*z; int n;                     /**/
  400. {    while(n--)marker_abs_3(*x++,*y++,*z++);
  401. }
  402. polymarker_abs_2(x,y,n) double *x,*y; int n;                          /**/
  403. {    while(n--)marker_abs_2(*x++,*y++);
  404. }
  405. polymarker_rel_3(x,y,z,n) double *x,*y,*z; int n;                     /**/
  406. {    double cx,cy,cz;
  407.     cx=cur_x; cy=cur_y; cz=cur_z;
  408.     while(n--)marker_abs_3(cx+ *x++,cy+ *y++,cz+ *z++);
  409. }
  410. polymarker_rel_2(x,y,n) double *x,*y; int n;                          /**/
  411. {    double cx,cy;
  412.     cx=cur_x; cy=cur_y; 
  413.     while(n--)marker_abs_2(cx+ *x++,cy+ *y++);
  414. }
  415.  
  416. /*    select_view_surface - select the screen mode */
  417. select_view_surface(mode) int mode;             /**/
  418. {    if(!initialized) init_graphics(mode);
  419.     initialized=1;
  420. }
  421.  
  422. /*    set character attributes */
  423. set_charsize(cw,ch)     double cw,ch;     {}                          /**/
  424. set_charplane(dx,dy,dz) double dx,dy,dz;  {}                          /**/
  425. set_charup_2(dx,dy)     double dx,dy;     {}                          /**/
  426. set_charup_3(dx,dy,dz)  double dx,dy,dz;  {}                          /**/
  427. set_charpath(i)         int i;            {}                          /**/
  428. set_charspace(x)        double x;         {}                          /**/
  429. set_charjust(i)         int i;            {}                          /**/
  430. set_charprecision(i)    int i;            {}                          /**/
  431.  
  432. /*    set_front_plane_clipping - enable depth clipping if i is nonzero */
  433. set_front_plane_clipping(i) int i;                                    /**/
  434. {    front_clipping=i; need_depth=persp_proj||front_clipping||back_clipping;
  435. }
  436.  
  437. /*    set_back_plane_clipping - enable depth clipping if i is nonzero */
  438. set_back_plane_clipping(i) int i;                                     /**/
  439. {    back_clipping=i; need_depth=persp_proj||front_clipping||back_clipping;
  440. }
  441.  
  442. /*    set line parameters */
  443. set_linestyle(style) int style;                                       /**/
  444. {    if(style<0) style=0;
  445.     else if(style>MAX_STYLE) style=MAX_STYLE;
  446.     current_linestyle=style;
  447.     reset_line();
  448. }
  449.  
  450.  
  451. set_linewidth(w) int w;                                               /**/
  452. {    if(w<1) w=1;
  453.     else if(w>25) w=25;
  454. #ifdef TEST
  455.     pen_diameter=4;/***************************************/
  456. #endif
  457.     current_linewidth=w;
  458.     reset_line();
  459. }
  460.  
  461. /*    set_marker_symbol - set symbol for marker & polymarker */
  462. set_marker_symbol(n) int n;                                           /**/
  463. {    if (n<1) n=1;
  464.     else {if (n>MAX_MARKER_SYMBOL) n=MAX_MARKER_SYMBOL;}
  465.     marker_symbol=n;
  466. }
  467.  
  468. /*    terminate_core - terminate graphics */
  469. terminate_core()                                                      /**/
  470. {if(initialized) finish_graphics(); 
  471. initialized=0;
  472. }
  473.  
  474. /*    terminate_view_surface - terminate the screen mode */
  475. terminate_view_surface()                                              /**/
  476. {if(initialized) finish_graphics(); 
  477. initialized=0;
  478. }
  479.  
  480. /*    text - display text string */
  481. text(s) char *s;                                                      /**/
  482. {    char *t;
  483.     t=s;
  484.     while(*t && isspace(*t)) t++;
  485.     if(*t==0) return;
  486.     if(front_clipping) {if(nn<=wmin) return;}
  487.     if(back_clipping) {if(nn>wmax) return;}
  488.     if(persp_proj)
  489.         {if(nn<=0.) return;
  490.         current_x=(int)(uu/nn); current_y=(int)(vv/nn);
  491.         }
  492.     if(clipping)
  493.         {if((current_x<wmin1)||(current_x>wmax1)||
  494.             (current_y<wmin2)||(current_y>wmax2)  ) return;
  495.         }
  496.     gotoxy(current_x,current_y);
  497.     (*draw_text)(s);
  498. #ifdef DEBUG
  499.     if(current_y<textymin) textymin=current_y;
  500.     if(current_y>textymax) textymax=current_y;
  501. #endif
  502. }
  503.  
  504. /*    viewport - define the area on the display to be used */
  505. viewport3(xmin,xmax,ymin,ymax,zmin,zmax)                              /**/
  506. double xmin,xmax,ymin,ymax,zmin,zmax;
  507. {    vp_xmin=xmin; vp_ymin=ymin; vp_zmin=zmin;
  508.     vp_xmax=xmax; vp_ymax=ymax; vp_zmax=zmax;
  509. }
  510.  
  511. /*    set_view_depth - set distances for depth clipping */
  512. set_view_depth(front_distance,back_distance)                          /**/
  513. double front_distance,back_distance;
  514. {    wmin=front_distance; wmax=back_distance;
  515. }
  516.  
  517. /*    view_plane_distance - set distance from vrp to view plane */
  518. view_plane_distance(v) double v; {vdist=v;}                           /**/
  519.  
  520. /*    view_plane_normal - define normal to view plane */
  521. view_plane_normal(dx,dy,dz) double dx,dy,dz;                          /**/
  522. {norm1=dx; norm2=dy; norm3=left_handed*dz;
  523. }
  524.  
  525. /*    view_reference_point - define view reference point */
  526. view_reference_point(x,y,z) double x,y,z; {vrp1=x; vrp2=y; vrp3=z;}   /**/
  527.  
  528. /*    view_up - define world direction which should appear "up" in view */
  529. view_up_2(dx,dy) double dx,dy; {view_up_3(dx,dy,0.);}                 /**/
  530. view_up_3(dx,dy,dz) double dx,dy,dz;                                  /**/
  531. {up1=dx; up2=dy; up3=left_handed*dz;}
  532.  
  533. /*    window - define the values of (rotated) world coordinates in the view */
  534. window(xmin,xmax,ymin,ymax) double xmin,xmax,ymin,ymax;               /**/
  535. {    umin=xmin; umax=xmax; vmin=ymin; vmax=ymax;
  536. }
  537.  
  538. /*--------------------------------------------------------------------------
  539.  
  540.         support functions
  541.  
  542. */
  543.  
  544. /*    clip - 3D clipping
  545.         returns nonzero if entire line is invisible
  546.         line is from a to b
  547.         clipping requirement is x DOT c > c[3], where dot
  548.                      product runs over first three elements */
  549. static int clip(double *a,double *b,double *c)
  550. {    register double *fp, q, qp;
  551.     double ac,bc;
  552.  
  553.     ac=a[0]*c[0] + a[1]*c[1] + a[2]*c[2];
  554.     bc=b[0]*c[0] + b[1]*c[1] + b[2]*c[2];
  555.     if(ac>bc){fp=a; a=b; b=fp; q=ac; ac=bc; bc=q; } /* ensure b "most visible" */
  556.     if(ac>=c[3]) return 0; /* both points visible */
  557.     if(bc<=c[3]) return 1; /* both points invisible */
  558.                 /* Now we know a DOT c < c[3] < b DOT c ,
  559.                    and we need a new a such that a DOT c = c[3] .
  560.                    We use q*a + (1-q)*b, where
  561.                    q = (c[3] - b DOT c)/((a - b) DOT c)        */
  562.     q=(c[3]-bc)/(ac-bc);    /* note ac < c[3] < bc, so denominator nonzero */
  563.     qp=1.-q;
  564.     a[0]=q*a[0] + qp*b[0];  a[1]=q*a[1] + qp*b[1];  a[2]=q*a[2] + qp*b[2];
  565.     return 0;                /* both points are now visible */
  566. }
  567.  
  568. /*--------------------------------------------------------------------------
  569.  
  570.         Interface routines between CORE graphics routines
  571.         and integer or "device coordinate" based routines
  572.  
  573. */
  574.  
  575.  
  576. /*    icline - draw line from cp to new position with clipping */
  577. icline(a1,a2,b1,b2)                                                   /**/
  578. int a1,a2,b1,b2;    /* beginning and end points of line */
  579. {    int t;                        /* temporary for exchanges */
  580.     
  581.     reversed=0;
  582.                 /* ensure a1<=b1 */
  583.     if(a1>b1) {t=a1; a1=b1; b1=t; t=a2; a2=b2; b2=t; reversed=1;}
  584.     if(a1<wmin1)
  585.         {if(b1<wmin1)return;    /* both points left of window */
  586.         a2=((wmin1-b1)*(long)a2+(a1-wmin1)*(long)b2)/(a1-b1); a1=wmin1;    /* find point on edge */
  587.         }
  588.     if(b1>wmax1)
  589.         {if(a1>wmax1)return;    /* both points right of window */
  590.         b2=((wmax1-a1)*(long)b2+(b1-wmax1)*(long)a2)/(b1-a1); b1=wmax1;    /* find point on edge */
  591.         }
  592.                 /* ensure a2<=b2 */
  593.     if(a2>b2) {t=a2; a2=b2; b2=t; t=a1; a1=b1; b1=t; reversed ^=1;}
  594.     if(a2<wmin2)
  595.         {if(b2<wmin2)return;    /* both points below window */
  596.         a1=((wmin2-b2)*(long)a1+(a2-wmin2)*(long)b1)/(a2-b2); a2=wmin2;    /* find point on edge */
  597.         }
  598.     if(b2>wmax2)
  599.         {if(a2>wmax2)return;    /* both points above window */
  600.         b1=((wmax2-a2)*(long)b1+(b2-wmax2)*(long)a1)/(b2-a2); b2=wmax2;    /* find point on edge */
  601.         }
  602.     (*after_clip)(a1,a2,b1,b2);
  603. }
  604.  
  605. #ifdef erasing
  606.  
  607. /*    icerase - erase line from cp to new position with clipping */
  608. icerase(a1,a2,b1,b2)                                                  /**/
  609. int a1,a2,b1,b2;    /* beginning and end points of line */
  610. {    t;                        /* temporary for exchanges */
  611.     
  612.     reversed=0;
  613.                             /* ensure a1<=b1 */
  614.     if(a1>b1) {t=a1; a1=b1; b1=t; t=a2; a2=b2; b2=t; reversed=1;}
  615.     if(a1<wmin1)
  616.         {if(b1<wmin1)return;    /* both points left of window */
  617.         a2=((wmin1-b1)*(long)a2+(a1-wmin1)*(long)b2)/(a1-b1); a1=wmin1;    /* find point on edge */
  618.         }
  619.     if(b1>wmax1)
  620.         {if(a1>wmax1)return;    /* both points right of window */
  621.         b2=((wmax1-a1)*(long)b2+(b1-wmax1)*(long)a2)/(b1-a1); b1=wmax1;    /* find point on edge */
  622.         }
  623.                                 /* ensure a2<=b2 */
  624.     if(a2>b2) {t=a2; a2=b2; b2=t; t=a1; a1=b1; b1=t; reversed ^=1;}
  625.     if(a2<wmin2)
  626.         {if(b2<wmin2)return;    /* both points below window */
  627.         a1=((wmin2-b2)*(long)a1+(a2-wmin2)*(long)b1)/(a2-b2); a2=wmin2;    /* find point on edge */
  628.         }
  629.     if(b2>wmax2)
  630.         {if(a2>wmax2)return;    /* both points above window */
  631.         b1=((wmax2-a2)*(long)b1+(b2-wmax2)*(long)a1)/(b2-a2); b2=wmax2;    /* find point on edge */
  632.         }
  633.     (*erase_line)(a1,a2,b1,b2);
  634. }
  635.  
  636. /*    ierase - erase line to new location    */
  637. ierase(x2,y2) int x2,y2;                                              /**/
  638. {    (*erase_line)(current_x,current_y,x2,y2);
  639.     current_x=x2; current_y=y2;
  640. }
  641.  
  642. #endif
  643.  
  644. /*    iwline - draw a wide line from (x1,y1) to (x2,y2) */
  645. iwline(x1,y1,x2,y2) int x1,y1,x2,y2;                                  /**/
  646. {    static int dx, dy, adx, ady, sx, sy, ty, s, c, xe, ye;
  647.     static int lgh, dl;
  648.  
  649.     dx=x2-x1; dy=y2-y1;
  650.     adx=abs(dx); ady=abs(dy*aspect);
  651.  
  652.                 /* lgh is approximately sqrt(dx**2 + (dy*aspect/10)**2)      
  653.                     Note ordering of calculations to avoid overflow. */
  654.                 /*
  655.                     This still overflows if dx = dy > 1310, so we cannot
  656.                     allow pixels_wide or pixels_high > 1310.  
  657.                     Also fails for dx=0, dy=1, and aspect<10 (i.e.  pixels
  658.                     that are wider than they are high).
  659.                 */
  660.     if(10*adx<ady) lgh=(ady/2 + 25*adx/ady*adx/6*5)/5;
  661.     else
  662.         {if(adx==0) return;
  663.                 /*
  664.                     This fails for dy = dx > 19660
  665.                 */
  666.         lgh = (adx*10 + (ady/24)*(ady/adx))/10;
  667.         }
  668.                 /* (sx,sy) is orthogonal to (dx,dy) */
  669.     dl=lgh>>1;
  670.     if(dy>0)
  671.         sx=((aspect*dy/10*aspect/10*current_linewidth+dl)/lgh)*pen_diameter;
  672.     else
  673.         sx=((aspect*dy/10*aspect/10*current_linewidth-dl)/lgh)*pen_diameter;
  674.     if(dx>0) ty=sy= -((current_linewidth*dx+dl)/lgh)*pen_diameter;
  675.     else     ty=sy= -((current_linewidth*dx-dl)/lgh)*pen_diameter;
  676.     if(sx<0) {sx= -sx; ty=sy= -sy;}
  677.     /* sx>=0, so shifting is OK.  sy may be negative, so use division */
  678.     x1-=sx>>1; xe=x2-=sx>>1; y1-=sy/2; ye=y2-=sy/2;
  679.     if(sy<0) {dy= -pen_diameter; sy= -sy;}
  680.     else     {dy=  pen_diameter;}
  681.     s=sx+sy;
  682.     c=(sx-sy)/2;
  683.     if(pen_diameter!=1)
  684.         {s /= pen_diameter;
  685.         (*after_wide)(x1+(sx*(current_linewidth-1))/current_linewidth,
  686.         y1+(ty*(current_linewidth-1))/current_linewidth ,x1, y1);
  687.         }
  688.     while(s--)
  689.         {(*after_wide)(x1, y1, x2, y2);
  690.         if(c<0) {c+=sx; y1+=dy; y2+=dy;}
  691.         else    {c-=sy; x1+=pen_diameter; x2+=pen_diameter;}
  692.         }
  693.     if(pen_diameter!=1)
  694.         (*after_wide)(xe, ye,
  695.         xe+(sx*(current_linewidth-1))/current_linewidth,
  696.         ye+(ty*(current_linewidth-1))/current_linewidth);
  697. }
  698.  
  699. /*    idline - draw dashed line from (x1,y1) to (x2,y2) */
  700. idline(x1,y1,x2,y2) int x1,y1,x2,y2;                                  /**/
  701. {    int x,y,mx,my,xa,ya,t;
  702.     int dx,dy,adx,ady,dist;
  703.     long remain;
  704.  
  705.     if(reversed) {t=x1; x1=x2; x2=t; t=y1; y1=y2; y2=t; reversed=0;}
  706.     if(using_dash_hardware)
  707.         {(*after_dashed)(x1,y1,x2,y2);
  708.         return;
  709.         }
  710.     dx=(x2-x1); dy=(y2-y1);
  711.     adx=abs(dx); ady=abs(dy*aspect);
  712.                 /* using the approximation
  713.                     sqrt(x**2 + y**2) approximately x + (5*x*x)/(12*y)
  714.                     when x > y                                           */
  715.                 /* note ordering of calculations to avoid overflow */
  716.     if(10*adx<ady) dist=(ady/2 + 25*adx/ady*adx/6*5)/5;
  717.     else
  718.         {if(adx==0)return;
  719.         dist=(adx*10 + (ady/24)*(ady/adx))/10;
  720.         }
  721.     remain=dist; xa=x1; ya=y1;
  722.     while(remain>step)
  723.         {remain-=step;
  724.         if(style_index&1)
  725.             {(*after_dashed)(xa,ya,(int)(x2-(remain*dx)/dist),
  726.                                    (int)(y2-(remain*dy)/dist)); 
  727.             }
  728.         else   {xa=x2-(remain*dx)/dist; ya=y2-(remain*dy)/dist;}
  729.         if(++style_index>=DASHES) style_index=0;
  730.         step=style_array[style_index];
  731.         }
  732.     if(style_index&1)(*after_dashed)(xa,ya,x2,y2);
  733.     step-=remain;
  734. }
  735.  
  736. /*    reset_line() - set up the three pointers to integer line routines */
  737. reset_line()                                                          /**/
  738. {    int i,j, using_width_hardware=0;
  739. /*
  740.     legal sequences...
  741.         line  (icline)  (idline)  draw_line
  742.         line  (idline)  iwline  (icline)  draw_line
  743.     ...because clipping must follow widening and widening must follow dashes.
  744.  
  745.     Hardware linestyles and wide lines may be used as follows...
  746.     available    requested    used
  747.     wide style    wide style    wide style
  748.     0    0        x    x        0    0   don't use what isn't there
  749.     0    1        x    0        0    0   don't use what isn't requested
  750.     0    1        0    1        0    1
  751.     0    1        1    1        0    0    on multiple passes, dashes don't match
  752.     1    0        0    x        0    0   don't use what isn't requested
  753.     1    0        1    0        1    0
  754.     1    0        1    1        0    0    since pen may not be round
  755.     1    1        A    B        A    B
  756. */
  757.     if(!initialized) init_graphics(0); /* note correct mode is unknown */
  758.     initialized=1;
  759.     if(new_linewidth)
  760.         {if(current_linewidth==1 || current_linestyle==SOLID || new_linestyle)
  761.             {(*new_linewidth)(current_linewidth);
  762.             using_width_hardware=1;
  763.             }
  764.         else (*new_linewidth)(1);
  765.         }
  766.     if(new_linestyle)
  767.         {if(current_linewidth==1 || current_linestyle==SOLID || new_linewidth)
  768.             (*new_linestyle)(current_linestyle);
  769.         else
  770.             (*new_linestyle)(SOLID);
  771.         }
  772.  
  773.     if((current_linewidth<=1) || using_width_hardware)
  774.         {after_wide=after_dashed=draw_line;
  775.         after_clip= (current_linestyle!=SOLID) ? idline : after_dashed;
  776.         after_line= clipping ? icline : after_clip;
  777.         using_dash_hardware = (new_linestyle != NULL);
  778.         }
  779.     else
  780.         {after_clip=draw_line;
  781.         after_wide= clipping ? icline : after_clip;
  782.         after_dashed= ((current_linewidth>1) && !using_width_hardware) 
  783.             ? iwline : after_wide;
  784.         after_line= (current_linestyle!=SOLID) ? idline : after_dashed;
  785.         using_dash_hardware=0;
  786.         }
  787. /*    printf("line routine locations...\n");
  788.     printf("after_line=%x \n",after_line);
  789.     printf("idline=%x  after_dashed=%x \n",idline,after_dashed);
  790.     printf("iwline=%x  after_wide=%x \n",iwline,after_wide);
  791.     printf("icline=%x  after_clip=%x \n",icline,after_clip);
  792.     printf("draw_line=%x \n",draw_line);
  793. */
  794.     aspect=10*best_height*pixels_wide/(best_width*pixels_high);
  795.     if(aspect < 10) aspect = 10;    /* prevents iwline and idline problems */
  796.     j=(current_linestyle-1)*DASHES;
  797.     for(i=0; i<DASHES; i++, j++)
  798.         {if(styles[j])
  799.             style_array[i]=
  800.                 (styles[j]+current_linewidth)*pen_diameter*aspect/10;
  801.         else style_array[i]=0;
  802.         }
  803.     step=style_array[0];
  804.     style_index=1;
  805. }
  806.  
  807. /*    initialize_view_surface - initialize the screen */
  808. initialize_view_surface(mode) int mode;                               /**/
  809. {    int i,j;
  810.     double t,xx,yy;
  811.     if(!initialized) init_graphics(mode);
  812.     initialized=1;
  813.     if(!scaled)
  814. /*
  815.     A rectangle with  width  = pixels_wide/best_width 
  816.                  and  height = pixels_high/best_height   
  817.     would be a square  
  818. */
  819.         {t=sqrt(pixels_wide/best_width/pixels_high*best_height);
  820.         xx=.1*t*pen_diameter;
  821.         yy=.2/t*pen_diameter;
  822.         j=mark_index[MAX_MARKER_SYMBOL]*4;
  823.         for (i=0 ; i<j ; i+=2)
  824.             {xm[i]*=xx; xm[i+1]*=yy;
  825.             }
  826.         scaled=1;
  827.         }
  828. }
  829.