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