home *** CD-ROM | disk | FTP | other *** search
- /*
- g3 - three dimensional graphics interface
-
- history...
- 24 Mar 90 Added function prototypes
- 29 Oct 87 Scaling marker symbols by the pen diameter.
- 28 Oct 87 In polymarker_*_*, drawing n markers rather than
- n-1. In polymarker_rel_2, saving current position
- and using marker_abs_2 rather than marker_rel_2.
- 16 Jun 87 For a wide line, displacing pen by pen_diameter on
- each pass. If pen_diameter is greater than 1, a
- stroke is added across each end to square it off.
- 16 May 87 Hid debugging code behind #ifdef's.
- Corrected aspect ratio scaling of marker symbols.
- 5 May 87 Using hardware for wide lines, if available.
- 24 Apr 86 If not widening, clipping first. Using hardware for
- dashed lines, if available.
- 19 Apr 86 Not displaying empty labels.
- 2 Dec 85 Using new gotoxy() call sequence.
- 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 <stdio.h>
- #include <math.h>
- #ifdef __TURBOC__
- #include <ctype.h>
- #endif
-
- #include "g.h"
- #include "g3.h"
-
- #ifdef DEBUG
- int textymin=400;
- int textymax=-400;
- #endif
-
- /* integer line drawing routines */
- static int
- icline(int a1, int a2, int b1, int b2),
- idline(int a1, int a2, int b1, int b2),
- iwline(int a1, int a2, int b1, int b2);
- static int clip( double *a, double *b, double *c );
- int (*after_line)(int a1, int a2, int b1, int b2);
- /* pointer to the line routine to follow line_abs_3() */
-
- /* variables */
-
- extern int debugging;
-
- static int
- /* pointer to the line routine to follow icline() */
- (*after_clip)(int a1, int a2, int b1, int b2),
- /* pointer to the line routine to follow iwline() */
- (*after_wide)(int a1, int a2, int b1, int b2),
- /* pointer to the line routine to follow idline() */
- (*after_dashed)(int a1, int a2, int b1, int b2),
- 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 */
- scaled=0, /* nonzero after markers have been rescaled */
-
- #define MAX_STYLE 9
- #define DASHES 8
- styles[MAX_STYLE*DASHES]={ /* 0 - solid */
- 5,8,5,8,5,8,5,8, /* 1 - dashed */
- 5,3,5,3,5,3,5,3, /* 2 - short dashes */
- 4,1,4,1,4,1,4,1, /* 3 - dotted */
- 4,8,4,1,4,8,4,1, /* 4 - dash-dot */
- 4,9,4,1,4,1,0,0, /* 5 - dash-dot-dot */
- 4,10,4,1,4,1,4,1, /* 6 - dash-dot-dot-dot */
- 4,10,4,10,4,1,0,0, /* 7 - dash-dash-dot */
- 4,10,4,10,4,1,4,1, /* 8 - dash-dash-dot-dot */
- 10,15,10,15,10,15}, /* 9 - dashed */
- style_array[DASHES],/* array of currently used dash lengths
- in units of 1/8 pixel width */
- style_index=0, /* index into style_array[] */
- step=12, /* amount of current dash not yet drawn */
- using_dash_hardware=0, /* nonzero if linestyles implemented in
- hardware and we can use them (not widening) */
- 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 */
- initialized, /* nonzero after output driver is initialized */
- 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) (in g3.h) */
- 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 previous_x,previous_y;
- static double a[3],b[3];
- #ifdef TRACE
- {
- FILE *dfile;
- dfile = fopen("dfile","a");
- fprintf(dfile, "file %s line %3d: line_abs_3(%f,%f,%f)\n", __FILE__, __LINE__, x, y, z);
- fclose(dfile);
- }
- #endif /* TRACE */
- 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)
- {
- #ifdef DEBUG
- /*if(debugging)
- {printf("line (%10f,%10f,%10f) to (%10f,%10f,%10f) \n",
- a[0],a[1],a[2],b[0],b[1],b[2]);
- } */
- #endif
- 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, 19,24,28,32};
- static int xm[]=
- /* x1 y1 x2 y2 ...for each line segment */
- {00,00,00,00, /* dot */
- 00,-20,00,20, -40,00,40,00, /* plus */
- -20,-18,20,18, -20,18,20,-18, -40,00,40,00, /* asterisk */
-
- -20,18,20,18, 20,18,40,00, 40,00,20,-18, /* hexagon */
- 20,-18,-20,-18, -20,-18,-40,00, -40,00,-20,18,
- -36,-18,36,18, 36,-18,-36,18, /* cross */
- -36,0,-36,18, -36,18,36,18, /* square */
- 36,18,36,-18, 36,-18,-36,-18, -36,-18,-36,0,
-
- 20,-10,40,00, 40,00,00,20, /* diamond */
- 00,20,-40,00, -40,00,00,-20, 00,-20,20,-10,
- 00,-20,-40,-20, -40,-20,00,20, /* triangle, point up */
- 00,20,40,-20, 40,-20,00,-20,
- 00,20,-40,20, -40,20,00,-20, /* triangle, point down */
- 00,-20,40,20, 40,20,00,20
-
- };
- #define MAX_MARKER_SYMBOL 9
-
- marker_abs_3(x,y,z) double x,y,z; /**/
- { int i, j, resetting;
- 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,char_height); printf("x,y=%d,%d",current_x,current_y);
- gotoxy(0,2*char_height);
- 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,3*char_height);
- i=mark_index[marker_symbol-1];
- printf("ym[%d...%d]=%d",i,j,ym[i]);
- for(i++ ;i<j; i++) printf(", %d",ym[i]);
- */
- resetting=0;
- if(new_linestyle &&
- current_linestyle!=SOLID &&
- (current_linewidth==1 || new_linewidth))
- {resetting=1;
- (*new_linestyle)(SOLID);
- }
- 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]);
- if(resetting) reset_line();
- /* 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; /**/
- {
- move_rel_3(*x++,*y++,*z++);
- while(--n)line_abs_3(*x++, *y++, *z++);
- }
- polyline_rel_2(x,y,n) double *x,*y; int n; /**/
- {
- move_rel_2(*x++,*y++); while(--n)line_rel_2(*x++,*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 sx,sy;
- move_rel_2(*x++,*y++); sx=cur_x; sy=cur_y;
- while(--n)line_rel_2(*x++, *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;
- cx=cur_x; cy=cur_y;
- while(n--)marker_abs_2(cx+ *x++,cy+ *y++);
- }
-
- /* select_view_surface - select the screen mode */
- select_view_surface(mode) int mode; /**/
- { if(!initialized) init_graphics(mode);
- initialized=1;
- }
-
- /* 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(style) int style; /**/
- { if(style<0) style=0;
- else if(style>MAX_STYLE) style=MAX_STYLE;
- current_linestyle=style;
- reset_line();
- }
-
-
- set_linewidth(w) int w; /**/
- { if(w<1) w=1;
- else if(w>25) w=25;
- #ifdef TEST
- pen_diameter=4;/***************************************/
- #endif
- 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() /**/
- {if(initialized) finish_graphics();
- initialized=0;
- }
-
- /* terminate_view_surface - terminate the screen mode */
- terminate_view_surface() /**/
- {if(initialized) finish_graphics();
- initialized=0;
- }
-
- /* text - display text string */
- text(s) char *s; /**/
- { char *t;
- t=s;
- while(*t && isspace(*t)) t++;
- if(*t==0) return;
- 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,current_y);
- (*draw_text)(s);
- #ifdef DEBUG
- if(current_y<textymin) textymin=current_y;
- if(current_y>textymax) textymax=current_y;
- #endif
- }
-
- /* 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
- returns nonzero if entire line is invisible
- line is from a to b
- clipping requirement is x DOT c > c[3], where dot
- product runs over first three elements */
- static int clip(double *a,double *b,double *c)
- { 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;
- /* 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 dx, dy, adx, ady, sx, sy, ty, s, c, xe, ye;
- static int lgh, dl;
-
- dx=x2-x1; dy=y2-y1;
- adx=abs(dx); ady=abs(dy*aspect);
-
- /* lgh is approximately sqrt(dx**2 + (dy*aspect/10)**2)
- Note ordering of calculations to avoid overflow. */
- /*
- This still overflows if dx = dy > 1310, so we cannot
- allow pixels_wide or pixels_high > 1310.
- Also fails for dx=0, dy=1, and aspect<10 (i.e. pixels
- that are wider than they are high).
- */
- if(10*adx<ady) lgh=(ady/2 + 25*adx/ady*adx/6*5)/5;
- else
- {if(adx==0) return;
- /*
- This fails for dy = dx > 19660
- */
- lgh = (adx*10 + (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)*pen_diameter;
- else
- sx=((aspect*dy/10*aspect/10*current_linewidth-dl)/lgh)*pen_diameter;
- if(dx>0) ty=sy= -((current_linewidth*dx+dl)/lgh)*pen_diameter;
- else ty=sy= -((current_linewidth*dx-dl)/lgh)*pen_diameter;
- if(sx<0) {sx= -sx; ty=sy= -sy;}
- /* sx>=0, so shifting is OK. sy may be negative, so use division */
- x1-=sx>>1; xe=x2-=sx>>1; y1-=sy/2; ye=y2-=sy/2;
- if(sy<0) {dy= -pen_diameter; sy= -sy;}
- else {dy= pen_diameter;}
- s=sx+sy;
- c=(sx-sy)/2;
- if(pen_diameter!=1)
- {s /= pen_diameter;
- (*after_wide)(x1+(sx*(current_linewidth-1))/current_linewidth,
- y1+(ty*(current_linewidth-1))/current_linewidth ,x1, y1);
- }
- while(s--)
- {(*after_wide)(x1, y1, x2, y2);
- if(c<0) {c+=sx; y1+=dy; y2+=dy;}
- else {c-=sy; x1+=pen_diameter; x2+=pen_diameter;}
- }
- if(pen_diameter!=1)
- (*after_wide)(xe, ye,
- xe+(sx*(current_linewidth-1))/current_linewidth,
- ye+(ty*(current_linewidth-1))/current_linewidth);
- }
-
- /* 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;
-
- if(reversed) {t=x1; x1=x2; x2=t; t=y1; y1=y2; y2=t; reversed=0;}
- if(using_dash_hardware)
- {(*after_dashed)(x1,y1,x2,y2);
- return;
- }
- 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/2 + 25*adx/ady*adx/6*5)/5;
- else
- {if(adx==0)return;
- dist=(adx*10 + (ady/24)*(ady/adx))/10;
- }
- remain=dist; xa=x1; ya=y1;
- 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;}
- if(++style_index>=DASHES) style_index=0;
- step=style_array[style_index];
- }
- if(style_index&1)(*after_dashed)(xa,ya,x2,y2);
- step-=remain;
- }
-
- /* reset_line() - set up the three pointers to integer line routines */
- reset_line() /**/
- { int i,j, using_width_hardware=0;
- /*
- legal sequences...
- line (icline) (idline) draw_line
- line (idline) iwline (icline) draw_line
- ...because clipping must follow widening and widening must follow dashes.
-
- Hardware linestyles and wide lines may be used as follows...
- available requested used
- wide style wide style wide style
- 0 0 x x 0 0 don't use what isn't there
- 0 1 x 0 0 0 don't use what isn't requested
- 0 1 0 1 0 1
- 0 1 1 1 0 0 on multiple passes, dashes don't match
- 1 0 0 x 0 0 don't use what isn't requested
- 1 0 1 0 1 0
- 1 0 1 1 0 0 since pen may not be round
- 1 1 A B A B
- */
- if(!initialized) init_graphics(0); /* note correct mode is unknown */
- initialized=1;
- if(new_linewidth)
- {if(current_linewidth==1 || current_linestyle==SOLID || new_linestyle)
- {(*new_linewidth)(current_linewidth);
- using_width_hardware=1;
- }
- else (*new_linewidth)(1);
- }
- if(new_linestyle)
- {if(current_linewidth==1 || current_linestyle==SOLID || new_linewidth)
- (*new_linestyle)(current_linestyle);
- else
- (*new_linestyle)(SOLID);
- }
-
- if((current_linewidth<=1) || using_width_hardware)
- {after_wide=after_dashed=draw_line;
- after_clip= (current_linestyle!=SOLID) ? idline : after_dashed;
- after_line= clipping ? icline : after_clip;
- using_dash_hardware = (new_linestyle != NULL);
- }
- else
- {after_clip=draw_line;
- after_wide= clipping ? icline : after_clip;
- after_dashed= ((current_linewidth>1) && !using_width_hardware)
- ? iwline : after_wide;
- after_line= (current_linestyle!=SOLID) ? idline : after_dashed;
- using_dash_hardware=0;
- }
- /* 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);
- if(aspect < 10) aspect = 10; /* prevents iwline and idline problems */
- j=(current_linestyle-1)*DASHES;
- for(i=0; i<DASHES; i++, j++)
- {if(styles[j])
- style_array[i]=
- (styles[j]+current_linewidth)*pen_diameter*aspect/10;
- else style_array[i]=0;
- }
- 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;
- if(!initialized) init_graphics(mode);
- initialized=1;
- if(!scaled)
- /*
- A rectangle with width = pixels_wide/best_width
- and height = pixels_high/best_height
- would be a square
- */
- {t=sqrt(pixels_wide/best_width/pixels_high*best_height);
- xx=.1*t*pen_diameter;
- yy=.2/t*pen_diameter;
- j=mark_index[MAX_MARKER_SYMBOL]*4;
- for (i=0 ; i<j ; i+=2)
- {xm[i]*=xx; xm[i+1]*=yy;
- }
- scaled=1;
- }
- }
-