1*15409Sralph #ifndef lint 2*15409Sralph static char sccsid[] = "@(#)arc.c 4.1 (Berkeley) 11/10/83"; 3*15409Sralph #endif 4*15409Sralph 5*15409Sralph #include "bg.h" 6*15409Sralph 7*15409Sralph /* should include test for equality? */ 8*15409Sralph #define side(x,y) (a*(x)+b*(y)+c > 0.0 ? 1 : -1) 9*15409Sralph 10*15409Sralph /* The beginning and ending points must be distinct. */ 11*15409Sralph arc(xc,yc,xbeg,ybeg,xend,yend) 12*15409Sralph int xc,yc,xbeg,ybeg,xend,yend; 13*15409Sralph { 14*15409Sralph double r, radius, costheta, sintheta; 15*15409Sralph double a, b, c, x, y, tempX; 16*15409Sralph int right_side; 17*15409Sralph 18*15409Sralph int screen_xc = scaleX(xc); 19*15409Sralph int screen_yc = scaleY(yc); 20*15409Sralph 21*15409Sralph /* It is more convienient to beg and end relative to center. */ 22*15409Sralph int screen_xbeg = scaleX(xbeg) - screen_xc; 23*15409Sralph int screen_ybeg = scaleY(ybeg) - screen_yc; 24*15409Sralph 25*15409Sralph int screen_xend = scaleX(xend) - screen_xc; 26*15409Sralph int screen_yend = scaleY(yend) - screen_yc; 27*15409Sralph 28*15409Sralph /* probably should check that arc is truely circular */ 29*15409Sralph r = sqrt( (double) (screen_xbeg*screen_xbeg + screen_ybeg*screen_ybeg) ); 30*15409Sralph 31*15409Sralph /* 32*15409Sralph This method is reasonably efficient, clean, and clever. 33*15409Sralph The easy part is generating the next point on the arc. This is 34*15409Sralph done by rotating the points by the angle theta. Theta is chosen 35*15409Sralph so that no rotation will cause more than one pixel of a move. 36*15409Sralph This corresponds to a triangle having x side of r and y side of 1. 37*15409Sralph The rotation is done (way) below inside the loop. 38*15409Sralph 39*15409Sralph Note: all calculations are done in screen coordinates. 40*15409Sralph */ 41*15409Sralph if (r <= 1.0) { 42*15409Sralph /* radius is mapped to length < 1*/ 43*15409Sralph point(xc,yc); 44*15409Sralph return; 45*15409Sralph } 46*15409Sralph 47*15409Sralph radius = sqrt(r*r + 1.0); 48*15409Sralph sintheta = 1.0/radius; 49*15409Sralph costheta = r/radius; 50*15409Sralph 51*15409Sralph /* 52*15409Sralph The hard part of drawing an arc is figuring out when to stop. 53*15409Sralph This method works by drawing the line from the beginning point 54*15409Sralph to the ending point. This splits the plane in half, with the 55*15409Sralph arc that we wish to draw on one side of the line. If we evaluate 56*15409Sralph side(x,y) = a*x + b*y + c, then all of the points on one side of the 57*15409Sralph line will result in side being positive, and all the points on the 58*15409Sralph other side of the line will result in side being negative. 59*15409Sralph 60*15409Sralph We want to draw the arc in a counter-clockwise direction, so we 61*15409Sralph must find out what the sign of "side" is for a point which is to the 62*15409Sralph "right" of a line drawn from "beg" to "end". A point which must lie 63*15409Sralph on the right is [xbeg + (yend-ybeg), ybeg - (xend-xbeg)]. (This 64*15409Sralph point is perpendicular to the line at "beg"). 65*15409Sralph 66*15409Sralph Thus, we compute side of the above point, and then compare the 67*15409Sralph sign of side for each new point with the sign of the above point. 68*15409Sralph When they are different, we terminate the loop. 69*15409Sralph */ 70*15409Sralph 71*15409Sralph a = (double) (screen_yend - screen_ybeg); 72*15409Sralph b = (double) (screen_xend - screen_xbeg); 73*15409Sralph c = (double) (screen_yend*screen_xbeg - screen_xend*screen_ybeg); 74*15409Sralph right_side = side(screen_xbeg + (screen_yend-screen_ybeg), 75*15409Sralph screen_ybeg - (screen_xend-screen_xbeg) ); 76*15409Sralph 77*15409Sralph x = screen_xbeg; 78*15409Sralph y = screen_ybeg; 79*15409Sralph move(xbeg, ybeg); 80*15409Sralph do { 81*15409Sralph currentx = screen_xc + (int) (x + 0.5); 82*15409Sralph currenty = screen_yc + (int) (y + 0.5); 83*15409Sralph putchar( ESC ); 84*15409Sralph printf(":%d;%dd", currentx, currenty); 85*15409Sralph tempX = x; 86*15409Sralph x = x*costheta - y*sintheta; 87*15409Sralph y = tempX*sintheta + y*costheta; 88*15409Sralph } while( side(x,y) == right_side ); 89*15409Sralph } 90