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: #if defined(DOSCCS) && !defined(lint)
8: static char sccsid[] = "@(#)arc.c 5.2.1 (2.11BSD GTE) 1/1/94";
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: }
Defined functions
arc
defined in line
18; used 2 times
Defined variables
sccsid
defined in line
8;
never used
Defined macros
side
defined in line
15; used 2 times