home *** CD-ROM | disk | FTP | other *** search
- /* g3 - three dimensional graphics interface
-
- history...
- 6 May 85 Added rudimentary text().
- 27 Apr 85 Not using iline(). changed from maybe_dashed, etc. to
- after_line, etc. so line routines could be executed in any order required.
- 18 Apr 85 different line widths and styles implemented.
- 7 Apr 85 Added linewidth and linestyle stubs.
- 9 Mar 85 hid (*erase_line)() references behind #ifdef's. changed
- init() references to init_graphics(), removed inquire_current_color().
- 15 Feb 85 iwline() installed - draws wide lines.
- */
-
- #include "math.h"
- #include "g.h"
- #include "g3.h"
-
- /* variables defined in file of hardware-dependent
- routines, such as gz.c */
-
- extern int pixels_wide,pixels_high; /* device size in pixels */
- extern double best_width,best_height; /* device height/width (proportional
- to actual dimensions in inches, but one of these *must* be 1,
- and the other must be in the range 0 to 1) */
-
- extern int char_rows, char_columns, /* text parameters */
- char_height, char_width,
- x_offset, y_offset;
-
- extern
- (*draw_line)(), /* (*draw_line)(x1,y1,x2,y2) int x1,y1,x2,y2;
- draws line from (x1,y1) to (x2,y2) */
- (*erase_line)(), /* (*erase_line)(x1,y1,x2,y2) int x1,y1,x2,y2;
- erases line from (x1,y1) to (x2,y2) */
- clear_graphics(), /* clears screen */
- init_graphics(),
- finish_graphics();
-
- extern int
- inquire_color(),
- inquire_linestyle(),
- inquire_linewidth();
-
- extern double inquire_intensity();
-
- extern int (*draw_line)(); /* (*draw_line)(x1,y1,x2,y2) int x1,y1,x2,y2;
- draws line from (x1,y1) to (x2,y2) */
- extern clear_graphics(); /* clears screen */
- extern init_graphics();
- extern finish_graphics();
-
- #ifdef erasing
- extern (*erase_line)(); /* (*erase_line)(x1,y1,x2,y2) int x1,y1,x2,y2;
- erases line from (x1,y1) to (x2,y2) */
- #endif
-
-
- int icline(),idline(),iwline(); /* integer line drawing routines */
-
- /* variables */
-
- extern int debugging;
-
- static int
- (*after_clip)(), /* points to the line routine to follow icline() */
- (*after_wide)(), /* points to the line routine to follow iwline() */
- (*after_dashed)(), /* points to the line routine to follow idline() */
- (*after_line)(), /* points to the line routine to follow line_abs_3() */
- aspect, /* 10*pixel height/pixel width */
- current_linewidth, /* width of line (units of pixel height) */
- current_linestyle=SOLID, /* style of line */
- current_x, current_y, /* current position (integer) */
- marker_symbol=1, /* current marker symbol */
- /* dashed dotted dash-dot dashed dotted dash-dot */
- 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},
- style_index=0, /* index into style_array[] */
- style_array[4], /* array of currently used dash lengths
- in units of 1/8 pixel width */
- step=12, /* amount of current dash not yet drawn */
- reversed=0; /* nonzero if endpoints of line have
- been swapped by icline() */
-
- extern int
- clipping, /* nonzero if clipping is enabled */
- front_clipping, /* nonzero if front clipping is enabled */
- back_clipping, /* nonzero if back clipping is enabled */
- graphics_level, /* level of CORE graphics requested */
- need_depth, /* nonzero if depth must be calculated (perspective
- projection or depth clipping */
- num_segments, /* number of segments that still exist */
- persp_proj, /* nonzero if perspective projection requested */
- segment_open, /* nonzero if a segment is open */
- wmin1,wmax1, /* minimum & maximum x values in device coordinates */
- wmin2,wmax2; /* minimum & maximum y values in device coordinates */
-
- extern double
- aspect_ratio, /* height/width ratio of display */
- left_handed, /* 1 for LH world coordinate system, -1 for RH */
- vdist, /* distance from viewpoint along view plane normal to
- viewplane */
- c_bottom[4],c_top[4], /* clip vectors...if x is visible, then */
- c_left[4],c_right[4], /* x[0]*c[0] + x[1]*c[1] + x[2]*c[2] > c[3] */
- c_near[4],c_far[4], /* for c equal to each of these six arrays */
- cur_x, cur_y, cur_z, /* current position (world coordinates) */
- uu, vv, nn, /* current position (viewport coordinates) */
- norm1, norm2, norm3, /* view plane normal */
- p1, p2, p3, /* direction for parallel projection, or
- center of projection */
- up1, up2, up3, /* view up vector */
- vrp1, vrp2, vrp3, /* view reference point */
-
- umin, umax, /* window in world coordinates */
- vmin, vmax,
- wmin, wmax,
- vp_xmin, vp_xmax, /* requested viewport in NDC */
- vp_ymin, vp_ymax,
- vp_zmin, vp_zmax,
- ndc_width, ndc_height, ndc_depth, /* requested limits on NDC values */
- rot11, rot12, rot13, rot14, /* rotation & projection matrix */
- rot21, rot22, rot23, rot24,
- rot31, rot32, rot33, rot34; /* (3rd row is for perspective projections) */
-
- /* CORE graphics routines */
-
- double charwidth, charheight;
- double dx_plane, dy_plane, dz_plane;
- double dx_charup, dy_charup, dz_charup;
- int charpath, charjust, charprecision;
- double charspace=0.;
-
- /* inquire character attributes */
-
- inquire_charsize(cw,ch) double *cw,*ch;
- {*cw=charwidth; *ch=charheight;
- }
-
- inquire_charplane(dx,dy,dz) double *dx,*dy,*dz;
- {*dx=dx_plane; *dy=dy_plane; *dz=dz_plane;
- }
-
- inquire_charup_2(dx,dy) double *dx,*dy;
- {*dx=dx_charup; *dy=dy_charup;
- }
-
- inquire_charup_3(dx,dy,dz) double *dx,*dy,*dz;
- {*dx=dx_charup; *dy=dy_charup; *dz=dz_charup;
- }
-
- double inquire_charspace() {return charspace;}
- int inquire_charpath() {return charpath;}
- int inquire_charjust() {return charjust;}
- int inquire_charprecision() {return charprecision;}
-
- /* inquire_current_position - report current position */
- inquire_current_position_2(x,y) double *x,*y; {*x=cur_x; *y=cur_y;}
- inquire_current_position_3(x,y,z) double *x,*y,*z;
- {*x=cur_x; *y=cur_y; *z=cur_z;
- }
-
- /* inquire line parameters */
- inquire_linestyle(n) int *n; {return (*n=current_linestyle);}
- inquire_linewidth(n) int *n; {return (*n=current_linewidth);}
- inquire_marker_symbol(n) int *n; {return (*n=marker_symbol);}
-
- /* inquire viewing parameters */
- inquire_ndc_space_2(w,h) double *w,*h;
- { *w=ndc_width; *h=ndc_height;
- }
- inquire_ndc_space_3(w,h,d) double *w,*h,*d;
- { *w=ndc_width; *h=ndc_height; *d=ndc_depth;
- }
-
- inquire_viewport_2(xmin,xmax,ymin,ymax)
- double *xmin,*xmax,*ymin,*ymax;
- { *xmin=vp_xmin; *xmax=vp_xmax;
- *ymin=vp_ymin; *ymax=vp_ymax;
- }
-
- inquire_viewport_3(xmin,xmax,ymin,ymax,zmin,zmax)
- double *xmin,*xmax,*ymin,*ymax,*zmin,*zmax;
- { *xmin=vp_xmin; *xmax=vp_xmax;
- *ymin=vp_ymin; *ymax=vp_ymax;
- *zmin=vp_zmin; *zmax=vp_zmax;
- }
-
- inquire_window(x1,x2,y1,y2) double *x1,*x2,*y1,*y2;
- { *x1=umin; *x2=umax; *y1=vmin; *y2=vmax;}
-
- inquire_open_temporary_segment() {return segment_open;}
-
- /* line - draw line from current position */
- line_abs_3(x,y,z) double x,y,z;
- { static int k1,k2,previous_x,previous_y;
- static double a[3],b[3];
- reversed=0;
- a[0]=uu; a[1]=vv; a[2]=nn; previous_x=current_x; previous_y=current_y;
- move_abs_3(x,y,z);
- b[0]=uu; b[1]=vv; b[2]=nn;
- if(persp_proj)
- {/* if(debugging)
- {printf("line (%10f,%10f,%10f) to (%10f,%10f,%10f) \n",
- a[0],a[1],a[2],b[0],b[1],b[2]);
- } */
- if(front_clipping)
- {if(clip(a,b,c_near)) return;
- }
- if(back_clipping)
- {if(clip(a,b,c_far)) return;
- }
- else if((a[2]>0.)&&(b[2]>0.)) {} /* can use integer clipping */
- else if(clipping)
- {/* clip along four planes */
- if(clip(a,b,c_left)||clip(a,b,c_right )||
- clip(a,b,c_top )||clip(a,b,c_bottom) ) return;
- if((a[2]<=0.)||(b[2]<=0.))return;
- }
- else return; /* one end invisible, clipping forbidden - omit line */
- (*after_line)((int)(a[0]/a[2]),(int)(a[1]/a[2]),
- (int)(b[0]/b[2]),(int)(b[1]/b[2]));
- }
- else /* parallel projection */
- {if(front_clipping||back_clipping)
- {if((front_clipping&&clip(a,b,c_near))||
- (back_clipping&&clip(a,b,c_far))) return;
- (*after_line)((int)a[0],(int)a[1],(int)b[0],(int)b[1]);
- }
- else (*after_line)(previous_x,previous_y,current_x,current_y);
- }
- }
-
- /* marker - display marker "n" */
- static int
- mark_index[]={0,1,3,6,12,14,18,22,25,28};
- static int xm[]=
- {0,0,0,0, /* dot */
- 0,-2,0,2, -5,0,5,0, /* plus */
- -2,-2,2,2, -2,2,2,-2, -4,0,4,0, /* asterisk */
- /* hexagon */
- -2,2,2,2, 2,2,4,0, 4,0,2,-2, 2,-2,-2,-2, -2,-2,-4,0, -4,0,-2,2,
- -5,-2,5,2, 5,-2,-5,2, /* cross */
- -5,-2,-5,2, -5,2,5,2, 5,2,5,-2, 5,-2,-5,-2, /* square */
- 0,-2,5,0, 5,0,0,2, 0,2,-5,0, -5,0,0,-2, /* diamond */
- -4,-2,0,2, 0,2,4,-2, -4,-2,4,-2, /* triangle */
- -4,2,0,-2, 0,-2,4,2, -4,2,4,2 /* triangle */
- };
- #define MAX_MARKER_SYMBOL 9
-
- marker_abs_3(x,y,z) double x,y,z;
- { int i,j;
- move_abs_3(x,y,z);
- if(front_clipping) {if(nn<=wmin) return;}
- if(back_clipping) {if(nn>wmax) return;}
- if(persp_proj)
- {if(nn<=0.) return;
- current_x=(int)(uu/nn); current_y=(int)(vv/nn);
- }
- if(clipping)
- {if((current_x<wmin1)||(current_x>wmax1)||
- (current_y<wmin2)||(current_y>wmax2) ) return;
- }
- j=mark_index[marker_symbol]*4;
- /*
- gotoxy(0,0); printf("x,y=%d,%d",current_x,current_y);
- gotoxy(0,1);
- i=mark_index[marker_symbol-1];
- printf("xm[%d...%d]=%d",i,j,xm[i]);
- for(i++ ;i<j; i++) printf(", %d",xm[i]);
- gotoxy(0,2);
- i=mark_index[marker_symbol-1];
- printf("ym[%d...%d]=%d",i,j,ym[i]);
- for(i++ ;i<j; i++) printf(", %d",ym[i]);
- */
- for (i=mark_index[marker_symbol-1]*4; i<j; i+=4)
- {(*draw_line)(current_x+xm[i], current_y+xm[i+1],
- current_x+xm[i+2],current_y+xm[i+3]);
- /* printf("\n*(draw_line)(%d,%d, %d,%d)",x1,y1,x2,y2); */
- }
- }
-
-
- /* move - move from current position */
- move_abs_3(x,y,z) double x,y,z;
- { cur_x=x; cur_y=y; cur_z=z;
- uu=rot11*x + rot12*y + rot13*z + rot14;
- vv=rot21*x + rot22*y + rot23*z + rot24;
- if(need_depth) {nn=rot31*x + rot32*y + rot33*z + rot34;}
- if(!persp_proj) {current_x=(int)uu; current_y=(int)vv;}
- }
-
- /* ndc_space - define limits on normalized device coordinate values
- w > h allows use of display device that's wider than it
- is high. (w and h in range 0. to 1., either w or h must be 1.) */
- ndc_space_2(w,h) double w,h; {ndc_space_3(w,h,1.);}
- ndc_space_3(w,h,d) double w,h,d;
- { ndc_width=w; if (vp_xmax>w) vp_xmax=w;
- ndc_height=h; if (vp_ymax>h) vp_ymax=h;
- ndc_depth=d;
- }
-
- /* new_frame - clear screen and redraw retained segments */
- new_frame() {clear_graphics();}
-
- /* parallel - define direction for parallel projection */
- parallel(x,y,z) double x,y,z;
- { p1=x; p2=y; p3=left_handed*z; persp_proj=0;
- need_depth=persp_proj||front_clipping||back_clipping;
- }
-
- /* perspective - define center of projection for perspective projection */
- perspective(x,y,z) double x,y,z;
- { p1=x; p2=y; p3=left_handed*z; persp_proj=1;
- need_depth=persp_proj||front_clipping||back_clipping;
- }
-
- /* polyline - draw lines connecting a series of points */
- polyline_abs_3(x,y,z,n) double *x,*y,*z; int n;
- { move_abs_3(*x++,*y++,*z++); while(--n)line_abs_3(*x++,*y++,*z++);
- }
- polyline_abs_2(x,y,n) double *x,*y; int n;
- { move_abs_2(*x++,*y++); while(--n)line_abs_2(*x++,*y++);
- }
- polyline_rel_3(x,y,z,n) double *x,*y,*z; int n;
- { double cx,cy,cz;
- cx=cur_x; cy=cur_y; cz=cur_z;
- move_rel_3(*x++,*y++,*z++);
- while(--n)line_abs_3(cx+ *x++,cy+ *y++,cz+ *z++);
- }
- polyline_rel_2(x,y,n) double *x,*y; int n;
- { double cx,cy;
- move_rel_2(*x++,*y++); while(--n)line_rel_2(cx+ *x++,cy+ *y++);
- }
-
- /* polygon - draw a polygon defined by its vertices */
- polygon_abs_3(x,y,z,n) double *x,*y,*z; int n;
- { double cx,cy,cz;
- move_abs_3(*x++,*y++,*z++);
- cx=cur_x; cy=cur_y; cz=cur_z;
- while(--n)line_abs_3(*x++,*y++,*z++);
- line_abs_3(cx,cy,cz);
- }
- polygon_abs_2(x,y,n) double *x,*y; int n;
- { double cx,cy;
- move_abs_2(*x++,*y++); cx=cur_x; cy=cur_y;
- while(--n)line_abs_2(*x++,*y++);
- line_abs_2(cx,cy);
- }
- polygon_rel_3(x,y,z,n) double *x,*y,*z; int n;
- { double cx,cy,cz;
- double sx,sy,sz;
- cx=cur_x; cy=cur_y; cz=cur_z;
- move_rel_3(*x++,*y++,*z++); sx=cur_x; sy=cur_y; sz=cur_z;
- while(--n)line_abs_3(cx+ *x++,cy+ *y++,cz+ *z++);
- line_abs_3(sx,sy,sz);
- }
- polygon_rel_2(x,y,n) double *x,*y; int n;
- { double cx,cy;
- double sx,sy;
- move_rel_2(*x++,*y++); sx=cur_x; sy=cur_y;
- while(--n)line_rel_2(cx+ *x++,cy+ *y++);
- line_abs_2(sx,sy);
- }
-
- /* polymarker - draw markers at a series of points */
- polymarker_abs_3(x,y,z,n) double *x,*y,*z; int n;
- { while(--n)marker_abs_3(*x++,*y++,*z++);
- }
- polymarker_abs_2(x,y,n) double *x,*y; int n;
- { while(--n)marker_abs_2(*x++,*y++);
- }
- polymarker_rel_3(x,y,z,n) double *x,*y,*z; int n;
- { double cx,cy,cz;
- cx=cur_x; cy=cur_y; cz=cur_z;
- while(--n)marker_abs_3(cx+ *x++,cy+ *y++,cz+ *z++);
- }
- polymarker_rel_2(x,y,n) double *x,*y; int n;
- { double cx,cy;
- while(--n)marker_rel_2(cx+ *x++,cy+ *y++);
- }
-
- /* select_view_surface - select the screen mode */
- select_view_surface(mode) int mode; {init_graphics(mode);}
-
- /* set character attributes */
- set_charsize(cw,ch) double cw,ch; {}
- set_charplane(dx,dy,dz) double dx,dy,dz; {}
- set_charup_2(dx,dy) double dx,dy; {}
- set_charup_3(dx,dy,dz) double dx,dy,dz; {}
- set_charpath(i) int i; {}
- set_charspace(x) double x; {}
- set_charjust(i) int i; {}
- set_charprecision(i) int i; {}
-
- /* set_front_plane_clipping - enable depth clipping if i is nonzero */
- set_front_plane_clipping(i) int i;
- { front_clipping=i; need_depth=persp_proj||front_clipping||back_clipping;
- }
-
- /* set_back_plane_clipping - enable depth clipping if i is nonzero */
- set_back_plane_clipping(i) int i;
- { back_clipping=i; need_depth=persp_proj||front_clipping||back_clipping;
- }
-
- /* set line parameters */
- set_linestyle(w) int w;
- { if(w<0) w=0;
- else if(w>6) w=6;
- current_linestyle=w;
- reset_line();
- }
-
-
- set_linewidth(w) int w;
- { if(w<1) w=1;
- else if(w>25) w=25;
- current_linewidth=w;
- reset_line();
- }
-
- /* set_marker_symbol - set symbol for marker & polymarker */
- set_marker_symbol(n) int n;
- { if (n<1) n=1;
- else {if (n>MAX_MARKER_SYMBOL) n=MAX_MARKER_SYMBOL;}
- marker_symbol=n;
- }
-
- /* terminate_core - terminate graphics */
- terminate_core() {finish_graphics();}
-
- /* terminate_view_surface - terminate the screen mode */
- terminate_view_surface() {finish_graphics();}
-
- /* text - display text string */
- text(s) char *s;
- { if(front_clipping) {if(nn<=wmin) return;}
- if(back_clipping) {if(nn>wmax) return;}
- if(persp_proj)
- {if(nn<=0.) return;
- current_x=(int)(uu/nn); current_y=(int)(vv/nn);
- }
- if(clipping)
- {if((current_x<wmin1)||(current_x>wmax1)||
- (current_y<wmin2)||(current_y>wmax2) ) return;
- }
- gotoxy((current_x-x_offset)/char_width,(current_y-y_offset)/char_height);
- puts(s);
- }
-
- /* viewport - define the area on the display to be used */
- viewport3(xmin,xmax,ymin,ymax,zmin,zmax) double xmin,xmax,ymin,ymax,zmin,zmax;
- { vp_xmin=xmin; vp_ymin=ymin; vp_zmin=zmin;
- vp_xmax=xmax; vp_ymax=ymax; vp_zmax=zmax;
- }
-
- /* set_view_depth - set distances for depth clipping */
- set_view_depth(front_distance,back_distance) double front_distance,back_distance;
- { wmin=front_distance; wmax=back_distance;
- }
-
- /* view_plane_distance - set distance from vrp to view plane */
- view_plane_distance(v) double v; {vdist=v;}
-
- /* view_plane_normal - define normal to view plane */
- view_plane_normal(dx,dy,dz) double dx,dy,dz;
- {norm1=dx; norm2=dy; norm3=left_handed*dz;
- }
-
- /* view_reference_point - define view reference point */
- view_reference_point(x,y,z) double x,y,z; {vrp1=x; vrp2=y; vrp3=z;}
-
- /* view_up - define world direction which should appear "up" in view */
- view_up_2(dx,dy) double dx,dy; {view_up_3(dx,dy,0.);}
- view_up_3(dx,dy,dz) double dx,dy,dz; {up1=dx; up2=dy; up3=left_handed*dz;}
-
- /* window - define the values of (rotated) world coordinates in the view */
- window(xmin,xmax,ymin,ymax) double xmin,xmax,ymin,ymax;
- { umin=xmin; umax=xmax; vmin=ymin; vmax=ymax;
- }
-
- /*--------------------------------------------------------------------------
-
- support functions
-
- */
-
- /* clip - 3D clipping */
- int clip(a,b,c) /* returns nonzero if entire line is invisible */
- double *a,*b, /* line is from a to b */
- *c; /* clipping requirement is x DOT c > c[3], where dot
- product runs over first three elements */
- { register double *fp, q, qp;
- double ac,bc;
-
- ac=a[0]*c[0] + a[1]*c[1] + a[2]*c[2];
- bc=b[0]*c[0] + b[1]*c[1] + b[2]*c[2];
- if(ac>bc){fp=a; a=b; b=fp; q=ac; ac=bc; bc=q; } /* ensure b "most visible" */
- if(ac>=c[3]) return 0; /* both points visible */
- if(bc<=c[3]) return 1; /* both points invisible */
- /* Now we know a DOT c < c[3] < b DOT c ,
- and we need a new a such that a DOT c = c[3] .
- We use q*a + (1-q)*b, where
- q = (c[3] - b DOT c)/((a - b) DOT c) */
- q=(c[3]-bc)/(ac-bc); /* note ac < c[3] < bc, so denominator nonzero */
- qp=1.-q;
- a[0]=q*a[0] + qp*b[0]; a[1]=q*a[1] + qp*b[1]; a[2]=q*a[2] + qp*b[2];
- return 0; /* both points are now visible */
- }
-
- /*--------------------------------------------------------------------------
-
- Interface routines between CORE graphics routines
- and integer or "device coordinate" based routines
-
- */
-
-
- /* icline - draw line from cp to new position with clipping */
- icline(a1,a2,b1,b2) int a1,a2,b1,b2; /* beginning and end points of line */
- { int t; /* temporary for exchanges */
-
- reversed=0;
- /* printf("icline(%d,%d,%d,%d)\n",a1,a2,b1,b2); */
- /* ensure a1<=b1 */
- if(a1>b1) {t=a1; a1=b1; b1=t; t=a2; a2=b2; b2=t; reversed=1;}
- if(a1<wmin1)
- {if(b1<wmin1)return; /* both points left of window */
- a2=((wmin1-b1)*(long)a2+(a1-wmin1)*(long)b2)/(a1-b1); a1=wmin1; /* find point on edge */
- }
- if(b1>wmax1)
- {if(a1>wmax1)return; /* both points right of window */
- b2=((wmax1-a1)*(long)b2+(b1-wmax1)*(long)a2)/(b1-a1); b1=wmax1; /* find point on edge */
- }
- /* ensure a2<=b2 */
- if(a2>b2) {t=a2; a2=b2; b2=t; t=a1; a1=b1; b1=t; reversed ^=1;}
- if(a2<wmin2)
- {if(b2<wmin2)return; /* both points below window */
- a1=((wmin2-b2)*(long)a1+(a2-wmin2)*(long)b1)/(a2-b2); a2=wmin2; /* find point on edge */
- }
- if(b2>wmax2)
- {if(a2>wmax2)return; /* both points above window */
- b1=((wmax2-a2)*(long)b1+(b2-wmax2)*(long)a1)/(b2-a2); b2=wmax2; /* find point on edge */
- }
- (*after_clip)(a1,a2,b1,b2);
- }
-
- #ifdef erasing
-
- /* icerase - erase line from cp to new position with clipping */
- icerase(a1,a2,b1,b2) int a1,a2,b1,b2; /* beginning and end points of line */
- { t; /* temporary for exchanges */
-
- reversed=0;
- /* ensure a1<=b1 */
- if(a1>b1) {t=a1; a1=b1; b1=t; t=a2; a2=b2; b2=t; reversed=1;}
- if(a1<wmin1)
- {if(b1<wmin1)return; /* both points left of window */
- a2=((wmin1-b1)*(long)a2+(a1-wmin1)*(long)b2)/(a1-b1); a1=wmin1; /* find point on edge */
- }
- if(b1>wmax1)
- {if(a1>wmax1)return; /* both points right of window */
- b2=((wmax1-a1)*(long)b2+(b1-wmax1)*(long)a2)/(b1-a1); b1=wmax1; /* find point on edge */
- }
- /* ensure a2<=b2 */
- if(a2>b2) {t=a2; a2=b2; b2=t; t=a1; a1=b1; b1=t; reversed ^=1;}
- if(a2<wmin2)
- {if(b2<wmin2)return; /* both points below window */
- a1=((wmin2-b2)*(long)a1+(a2-wmin2)*(long)b1)/(a2-b2); a2=wmin2; /* find point on edge */
- }
- if(b2>wmax2)
- {if(a2>wmax2)return; /* both points above window */
- b1=((wmax2-a2)*(long)b1+(b2-wmax2)*(long)a1)/(b2-a2); b2=wmax2; /* find point on edge */
- }
- (*erase_line)(a1,a2,b1,b2);
- }
-
- /* ierase - erase line to new location */
- ierase(x2,y2) int x2,y2;
- { (*erase_line)(current_x,current_y,x2,y2);
- current_x=x2; current_y=y2;
- }
-
- #endif
-
- /* iwline - draw a wide line from (x1,y1) to (x2,y2) */
- iwline(x1,y1,x2,y2) int x1,y1,x2,y2;
- { static int cnt,dx,dy,adx,ady,sx,sy,s,c;
- static int lgh,dl;
- /* printf("\033Y\042\040iwline(%d,%d,%d,%d), step=%d",x1,y1,x2,y2,step); */
- /* printf("iwline(%d,%d,%d,%d), step=%d \n",x1,y1,x2,y2,step); */
- dx=x2-x1; dy=y2-y1;
- adx=abs(dx); ady=abs(dy*aspect);
- /* lgh is approximately sqrt(adx**2 + ady**2) */
- /* note ordering of calculations to avoid overflow */
- if(10*adx<ady) lgh=ady/10+25*adx/ady*adx/6;
- else
- {if(adx==0) return;
- lgh=adx+ady/24*(ady/adx)/10;
- }
- /* (sx,sy) is orthogonal to (dx,dy) */
- dl=lgh>>1;
- if(dy>0)sx=(aspect*dy/10*aspect/10*current_linewidth+dl)/lgh;
- else sx=(aspect*dy/10*aspect/10*current_linewidth-dl)/lgh;
- if(dx>0)sy= -(current_linewidth*dx+dl)/lgh;
- else sy= -(current_linewidth*dx-dl)/lgh;
- if(sx<0) {sx= -sx; sy= -sy;}
- x1-=sx>>1; x2-=sx>>1; y1-=sy/2; y2-=sy/2;
- if(sy<0) {dy= -1; sy= -sy;}
- else {dy= 1;}
- s=sx+sy; c=(sx-sy)/2;
- /* printf("\033Y\043\040iwline: sx=%d sy=%d s=%d c=%d dx=%d dy=%d \n",
- sx,sy,s,c,dx,dy); */
- while(s--)
- {(*after_wide)(x1,y1,x2,y2);
- /* printf("\033Y\044\040(*draw_line(%d,%d,%d,%d) \n",x1,y1,x2,y2); */
- if(c<0) {c+=sx; y1+=dy; y2+=dy;}
- else {c-=sy; x1++; x2++;}
- }
- /* printf("\033Y\042\040 ");
- printf("\033Y\043\040 "); */
- }
-
- /* idline - draw dashed line from (x1,y1) to (x2,y2) */
- idline(x1,y1,x2,y2) int x1,y1,x2,y2;
- { int x,y,mx,my,xa,ya,t;
- int dx,dy,adx,ady,dist;
- long remain;
- /* printf("\033Y\040\040idline(%d,%d,%d,%d), step=%d",x1,y1,x2,y2,step); */
- /* printf("idline(%d,%d,%d,%d), step=%d \n",x1,y1,x2,y2,step); */
- if(reversed) {t=x1; x1=x2; x2=t; t=y1; y1=y2; y2=t; reversed=0;}
- dx=(x2-x1); dy=(y2-y1);
- adx=abs(dx); ady=abs(dy*aspect);
- /* using the approximation
- sqrt(x**2 + y**2) approximately x + (5*x*x)/(12*y)
- when x > y */
- /* note ordering of calculations to avoid overflow */
- if(10*adx<ady) dist=ady/10+(((25*adx)/ady)*adx)/6;
- else
- {if(adx==0)return;
- dist=adx+((ady/24)*(ady/adx))/10;
- }
- remain=dist; xa=x1; ya=y1;
- /* printf("\033Y\041\040idline: dist=%d",dist); */
- while(remain>step)
- {remain-=step;
- if(style_index&1)
- {(*after_dashed)(xa,ya,(int)(x2-(remain*dx)/dist),
- (int)(y2-(remain*dy)/dist));
- }
- else {xa=x2-(remain*dx)/dist; ya=y2-(remain*dy)/dist;}
- style_index=(style_index+1)&3; step=style_array[style_index];
- }
- if(style_index&1)(*after_dashed)(xa,ya,x2,y2);
- step-=remain;
- /* printf("\033Y\040\040 ");
- printf("\033Y\041\040 "); */
- }
-
- ireport(a,b,c,d) int a,b,c,d;
- { printf("draw_line(%d,%d,%d,%d) \n",a,b,c,d);
- }
- /* reset_line() - set up the three pointers to integer line routines */
- reset_line()
- { int i,j;
- if( clipping && (current_linewidth<=1) && (current_linestyle!=SOLID) )
- {after_line=icline;
- after_clip=idline;
- after_wide=after_dashed=draw_line;
- }
- else
- {after_clip=draw_line;
- after_wide= clipping ? icline : after_clip;
- after_dashed= (current_linewidth>1) ? iwline : after_wide;
- after_line= (current_linestyle!=SOLID) ? idline : after_dashed;
- }
- /* printf("line routine locations...\n");
- printf("after_line=%x \n",after_line);
- printf("idline=%x after_dashed=%x \n",idline,after_dashed);
- printf("iwline=%x after_wide=%x \n",iwline,after_wide);
- printf("icline=%x after_clip=%x \n",icline,after_clip);
- printf("draw_line=%x \n",draw_line);
- */
- aspect=10*best_height*pixels_wide/(best_width*pixels_high);
- j=(current_linestyle-1)*4;
- for(i=0; i<4; i++)
- {style_array[i]=(styles[j++]+current_linewidth)*aspect/10;
- }
- step=style_array[0];
- style_index=1;
- }
-
- /* initialize_view_surface - initialize the screen */
- initialize_view_surface(mode) int mode;
- { int i,j;
- double t,xx,yy;
- init_graphics(mode);
- t=pixels_wide/best_height/pixels_high*best_width;
- xx=t/3.;
- yy=4./t;
- j=mark_index[MAX_MARKER_SYMBOL]*4;
- for (i=0 ; i<j ; i+=2)
- {xm[i]*=xx; xm[i+1]*=yy;
- }
- }