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

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