1*48504Sbostic /*- 2*48504Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48504Sbostic * All rights reserved. 4*48504Sbostic * 5*48504Sbostic * %sccs.include.proprietary.c% 619851Sdist */ 719851Sdist 815409Sralph #ifndef lint 9*48504Sbostic static char sccsid[] = "@(#)arc.c 5.3 (Berkeley) 04/22/91"; 10*48504Sbostic #endif /* not lint */ 1115409Sralph 1215409Sralph #include "bg.h" 1315409Sralph 1415409Sralph /* should include test for equality? */ 1515409Sralph #define side(x,y) (a*(x)+b*(y)+c > 0.0 ? 1 : -1) 1615409Sralph 1715409Sralph /* The beginning and ending points must be distinct. */ 1815409Sralph arc(xc,yc,xbeg,ybeg,xend,yend) 1915409Sralph int xc,yc,xbeg,ybeg,xend,yend; 2015409Sralph { 2115409Sralph double r, radius, costheta, sintheta; 2215409Sralph double a, b, c, x, y, tempX; 2315409Sralph int right_side; 2415409Sralph 2515409Sralph int screen_xc = scaleX(xc); 2615409Sralph int screen_yc = scaleY(yc); 2715409Sralph 2815409Sralph /* It is more convienient to beg and end relative to center. */ 2915409Sralph int screen_xbeg = scaleX(xbeg) - screen_xc; 3015409Sralph int screen_ybeg = scaleY(ybeg) - screen_yc; 3115409Sralph 3215409Sralph int screen_xend = scaleX(xend) - screen_xc; 3315409Sralph int screen_yend = scaleY(yend) - screen_yc; 3415409Sralph 3515409Sralph /* probably should check that arc is truely circular */ 3615409Sralph r = sqrt( (double) (screen_xbeg*screen_xbeg + screen_ybeg*screen_ybeg) ); 3715409Sralph 3815409Sralph /* 3915409Sralph This method is reasonably efficient, clean, and clever. 4015409Sralph The easy part is generating the next point on the arc. This is 4115409Sralph done by rotating the points by the angle theta. Theta is chosen 4215409Sralph so that no rotation will cause more than one pixel of a move. 4315409Sralph This corresponds to a triangle having x side of r and y side of 1. 4415409Sralph The rotation is done (way) below inside the loop. 4515409Sralph 4615409Sralph Note: all calculations are done in screen coordinates. 4715409Sralph */ 4815409Sralph if (r <= 1.0) { 4915409Sralph /* radius is mapped to length < 1*/ 5015409Sralph point(xc,yc); 5115409Sralph return; 5215409Sralph } 5315409Sralph 5415409Sralph radius = sqrt(r*r + 1.0); 5515409Sralph sintheta = 1.0/radius; 5615409Sralph costheta = r/radius; 5715409Sralph 5815409Sralph /* 5915409Sralph The hard part of drawing an arc is figuring out when to stop. 6015409Sralph This method works by drawing the line from the beginning point 6115409Sralph to the ending point. This splits the plane in half, with the 6215409Sralph arc that we wish to draw on one side of the line. If we evaluate 6315409Sralph side(x,y) = a*x + b*y + c, then all of the points on one side of the 6415409Sralph line will result in side being positive, and all the points on the 6515409Sralph other side of the line will result in side being negative. 6615409Sralph 6715409Sralph We want to draw the arc in a counter-clockwise direction, so we 6815409Sralph must find out what the sign of "side" is for a point which is to the 6915409Sralph "right" of a line drawn from "beg" to "end". A point which must lie 7015409Sralph on the right is [xbeg + (yend-ybeg), ybeg - (xend-xbeg)]. (This 7115409Sralph point is perpendicular to the line at "beg"). 7215409Sralph 7315409Sralph Thus, we compute side of the above point, and then compare the 7415409Sralph sign of side for each new point with the sign of the above point. 7515409Sralph When they are different, we terminate the loop. 7615409Sralph */ 7715409Sralph 7815409Sralph a = (double) (screen_yend - screen_ybeg); 7915409Sralph b = (double) (screen_xend - screen_xbeg); 8015409Sralph c = (double) (screen_yend*screen_xbeg - screen_xend*screen_ybeg); 8115409Sralph right_side = side(screen_xbeg + (screen_yend-screen_ybeg), 8215409Sralph screen_ybeg - (screen_xend-screen_xbeg) ); 8315409Sralph 8415409Sralph x = screen_xbeg; 8515409Sralph y = screen_ybeg; 8615409Sralph move(xbeg, ybeg); 8715409Sralph do { 8815409Sralph currentx = screen_xc + (int) (x + 0.5); 8915409Sralph currenty = screen_yc + (int) (y + 0.5); 9015409Sralph putchar( ESC ); 9115409Sralph printf(":%d;%dd", currentx, currenty); 9215409Sralph tempX = x; 9315409Sralph x = x*costheta - y*sintheta; 9415409Sralph y = tempX*sintheta + y*costheta; 9515409Sralph } while( side(x,y) == right_side ); 9615409Sralph } 97