|
|
1.1 root 1: /* @(#)draw.c 1.1 */
2: #include <stdio.h>
3: #include <math.h>
4: #define PI 3.141592654
5: #define hmot(n) hpos += n
6: #define hgoto(n) hpos = n
7: #define vmot(n) vgoto(vpos + n)
8:
9: extern int hpos;
10: extern int vpos;
11: extern int size;
12: extern short *pstab;
13: extern int DX; /* step size in x */
14: extern int DY; /* step size in y */
15: extern int drawdot; /* character to use when drawing */
16: extern int drawsize; /* shrink point size by this facter */
17:
18: int maxdots = 32000; /* maximum number of dots in an object */
19:
20: #define sgn(n) ((n > 0) ? 1 : ((n < 0) ? -1 : 0))
21: #define abs(n) ((n) >= 0 ? (n) : -(n))
22: #define max(x,y) ((x) > (y) ? (x) : (y))
23: #define min(x,y) ((x) < (y) ? (x) : (y))
24: #define arcmove(x,y) { hgoto(x); vmot(-vpos-(y)); }
25:
26: drawline(dx, dy, s) /* draw line from here to dx, dy using s */
27: int dx, dy;
28: char *s;
29: {
30: int xd, yd;
31: float val, slope;
32: int i, numdots;
33: int dirmot, perp;
34: int motincr, perpincr;
35: int ohpos, ovpos, osize, ofont;
36: float incrway;
37:
38: osize = size;
39: setsize(t_size(pstab[osize-1] / drawsize));
40: ohpos = hpos;
41: ovpos = vpos;
42: xd = dx / DX;
43: yd = dy / DX;
44: if (xd == 0) {
45: numdots = abs (yd);
46: numdots = min(numdots, maxdots);
47: motincr = DX * sgn (yd);
48: for (i = 0; i < numdots; i++) {
49: vmot(motincr);
50: put1(drawdot);
51: }
52: vgoto(ovpos + dy);
53: setsize(osize);
54: return;
55: }
56: if (yd == 0) {
57: numdots = abs (xd);
58: motincr = DX * sgn (xd);
59: for (i = 0; i < numdots; i++) {
60: hmot(motincr);
61: put1(drawdot);
62: }
63: hgoto(ohpos + dx);
64: setsize(osize);
65: return;
66: }
67: if (abs (xd) > abs (yd)) {
68: val = slope = (float) xd/yd;
69: numdots = abs (xd);
70: numdots = min(numdots, maxdots);
71: dirmot = 'h';
72: perp = 'v';
73: motincr = DX * sgn (xd);
74: perpincr = DX * sgn (yd);
75: }
76: else {
77: val = slope = (float) yd/xd;
78: numdots = abs (yd);
79: numdots = min(numdots, maxdots);
80: dirmot = 'v';
81: perp = 'h';
82: motincr = DX * sgn (yd);
83: perpincr = DX * sgn (xd);
84: }
85: incrway = sgn ((int) slope);
86: for (i = 0; i < numdots; i++) {
87: val -= incrway;
88: if (dirmot == 'h')
89: hmot(motincr);
90: else
91: vmot(motincr);
92: if (val * slope < 0) {
93: if (perp == 'h')
94: hmot(perpincr);
95: else
96: vmot(perpincr);
97: val += slope;
98: }
99: put1(drawdot);
100: }
101: hgoto(ohpos + dx);
102: vgoto(ovpos + dy);
103: setsize(osize);
104: }
105:
106: drawwig(s) /* draw wiggly line */
107: char *s;
108: {
109: int x[50], y[50], xp, yp, pxp, pyp;
110: float t1, t2, t3, w;
111: int i, j, numdots, N;
112: int osize, ofont;
113: char temp[50], *p, *getstr();
114:
115: osize = size;
116: setsize(t_size(pstab[osize-1] / drawsize));
117: p = s;
118: for (N = 2; (p=getstr(p,temp)) != NULL && N < sizeof(x)/sizeof(x[0]); N++) {
119: x[N] = atoi(temp);
120: p = getstr(p, temp);
121: y[N] = atoi(temp);
122: }
123: x[0] = x[1] = hpos;
124: y[0] = y[1] = vpos;
125: for (i = 1; i < N; i++) {
126: x[i+1] += x[i];
127: y[i+1] += y[i];
128: }
129: x[N] = x[N-1];
130: y[N] = y[N-1];
131: pxp = pyp = -9999;
132: for (i = 0; i < N-1; i++) { /* interval */
133: numdots = (dist(x[i],y[i], x[i+1],y[i+1]) + dist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2;
134: numdots /= DX;
135: numdots = min(numdots, maxdots);
136: for (j = 0; j < numdots; j++) { /* points within */
137: w = (float) j / numdots;
138: t1 = 0.5 * w * w;
139: w = w - 0.5;
140: t2 = 0.75 - w * w;
141: w = w - 0.5;
142: t3 = 0.5 * w * w;
143: xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
144: yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
145: if (xp != pxp || yp != pyp) {
146: hgoto(xp);
147: vgoto(yp);
148: put1(drawdot);
149: pxp = xp;
150: pyp = yp;
151: }
152: }
153: }
154: setsize(osize);
155: }
156:
157: char *getstr(p, temp) /* copy next non-blank string from p to temp, update p */
158: char *p, *temp;
159: {
160: while (*p == ' ' || *p == '\t' || *p == '\n')
161: p++;
162: if (*p == '\0') {
163: temp[0] = 0;
164: return(NULL);
165: }
166: while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
167: *temp++ = *p++;
168: *temp = '\0';
169: return(p);
170: }
171:
172: drawcirc(d)
173: {
174: int xc, yc;
175:
176: xc = hpos;
177: yc = vpos;
178: conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
179: hgoto(xc + d); /* circle goes to right side */
180: vgoto(yc);
181: }
182:
183: dist(x1, y1, x2, y2) /* integer distance from x1,y1 to x2,y2 */
184: {
185: float dx, dy;
186:
187: dx = x2 - x1;
188: dy = y2 - y1;
189: return sqrt(dx*dx + dy*dy) + 0.5;
190: }
191:
192: drawarc(dx1, dy1, dx2, dy2)
193: {
194: int x0, y0, x2, y2, r;
195:
196: x0 = hpos + dx1; /* center */
197: y0 = vpos + dy1;
198: x2 = x0 + dx2; /* "to" */
199: y2 = y0 + dy2;
200: r = sqrt((float) dx1 * dx1 + (float) dy1 * dy1) + 0.5;
201: conicarc(x0, -y0, hpos, -vpos, x2, -y2, r, r);
202: }
203:
204: drawellip(a, b)
205: {
206: int xc, yc;
207:
208: xc = hpos;
209: yc = vpos;
210: conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
211: hgoto(xc + a);
212: vgoto(yc);
213: }
214:
215: #define sqr(x) (long int)(x)*(x)
216:
217: conicarc(x, y, x0, y0, x1, y1, a, b)
218: {
219: /* based on Bresenham, CACM, Feb 77, pp 102-3 */
220: /* by Chris Van Wyk */
221: /* capitalized vars are an internal reference frame */
222: long dotcount = 0;
223: int osize, ofont;
224: int xs, ys, xt, yt, Xs, Ys, qs, Xt, Yt, qt,
225: M1x, M1y, M2x, M2y, M3x, M3y,
226: Q, move, Xc, Yc;
227: int ox1, oy1;
228: long delta;
229: float xc, yc;
230: float radius, slope;
231: float xstep, ystep;
232:
233: osize = size;
234: setsize(t_size(pstab[osize-1] / drawsize));
235: ox1 = x1;
236: oy1 = y1;
237: if (a != b) /* an arc of an ellipse; internally, will still think of circle */
238: if (a > b) {
239: xstep = (float)a / b;
240: ystep = 1;
241: radius = b;
242: } else {
243: xstep = 1;
244: ystep = (float)b / a;
245: radius = a;
246: }
247: else { /* a circular arc; radius is computed from center and first point */
248: xstep = ystep = 1;
249: radius = sqrt((float)(sqr(x0 - x) + sqr(y0 - y)));
250: }
251:
252:
253: xc = x0;
254: yc = y0;
255: /* now, use start and end point locations to figure out
256: the angle at which start and end happen; use these
257: angles with known radius to figure out where start
258: and end should be
259: */
260: slope = atan2((double)(y0 - y), (double)(x0 - x) );
261: if (slope == 0.0 && x0 < x)
262: slope = 3.14159265;
263: x0 = x + radius * cos(slope) + 0.5;
264: y0 = y + radius * sin(slope) + 0.5;
265: slope = atan2((double)(y1 - y), (double)(x1 - x));
266: if (slope == 0.0 && x1 < x)
267: slope = 3.14159265;
268: x1 = x + radius * cos(slope) + 0.5;
269: y1 = y + radius * sin(slope) + 0.5;
270: /* step 2: translate to zero-centered circle */
271: xs = x0 - x;
272: ys = y0 - y;
273: xt = x1 - x;
274: yt = y1 - y;
275: /* step 3: normalize to first quadrant */
276: if (xs < 0)
277: if (ys < 0) {
278: Xs = abs(ys);
279: Ys = abs(xs);
280: qs = 3;
281: M1x = 0;
282: M1y = -1;
283: M2x = 1;
284: M2y = -1;
285: M3x = 1;
286: M3y = 0;
287: } else {
288: Xs = abs(xs);
289: Ys = abs(ys);
290: qs = 2;
291: M1x = -1;
292: M1y = 0;
293: M2x = -1;
294: M2y = -1;
295: M3x = 0;
296: M3y = -1;
297: }
298: else if (ys < 0) {
299: Xs = abs(xs);
300: Ys = abs(ys);
301: qs = 0;
302: M1x = 1;
303: M1y = 0;
304: M2x = 1;
305: M2y = 1;
306: M3x = 0;
307: M3y = 1;
308: } else {
309: Xs = abs(ys);
310: Ys = abs(xs);
311: qs = 1;
312: M1x = 0;
313: M1y = 1;
314: M2x = -1;
315: M2y = 1;
316: M3x = -1;
317: M3y = 0;
318: }
319:
320:
321: Xc = Xs;
322: Yc = Ys;
323: if (xt < 0)
324: if (yt < 0) {
325: Xt = abs(yt);
326: Yt = abs(xt);
327: qt = 3;
328: } else {
329: Xt = abs(xt);
330: Yt = abs(yt);
331: qt = 2;
332: }
333: else if (yt < 0) {
334: Xt = abs(xt);
335: Yt = abs(yt);
336: qt = 0;
337: } else {
338: Xt = abs(yt);
339: Yt = abs(xt);
340: qt = 1;
341: }
342:
343:
344: /* step 4: calculate number of quadrant crossings */
345: if (((4 + qt - qs)
346: % 4 == 0)
347: && (Xt <= Xs)
348: && (Yt >= Ys)
349: )
350: Q = 3;
351: else
352: Q = (4 + qt - qs) % 4 - 1;
353: /* step 5: calculate initial decision difference */
354: delta = sqr(Xs + 1)
355: + sqr(Ys - 1)
356: -sqr(xs)
357: -sqr(ys);
358: /* here begins the work of drawing
359: we hope it ends here too */
360: while ((Q >= 0)
361: || ((Q > -2)
362: && ((Xt > Xc)
363: && (Yt < Yc)
364: )
365: )
366: ) {
367: if (dotcount++ % DX == 0)
368: putdot((int)xc, (int)yc);
369: if (Yc < 0.5) {
370: /* reinitialize */
371: Xs = Xc = 0;
372: Ys = Yc = sqrt((float)(sqr(xs) + sqr(ys)));
373: delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
374: Q--;
375: M1x = M3x;
376: M1y = M3y;
377: {
378: int T;
379: T = M2y;
380: M2y = M2x;
381: M2x = -T;
382: T = M3y;
383: M3y = M3x;
384: M3x = -T;
385: }
386: } else {
387: if (delta <= 0)
388: if (2 * delta + 2 * Yc - 1 <= 0)
389: move = 1;
390: else
391: move = 2;
392: else if (2 * delta - 2 * Xc - 1 <= 0)
393: move = 2;
394: else
395: move = 3;
396: switch (move) {
397: case 1:
398: Xc++;
399: delta += 2 * Xc + 1;
400: xc += M1x * xstep;
401: yc += M1y * ystep;
402: break;
403: case 2:
404: Xc++;
405: Yc--;
406: delta += 2 * Xc - 2 * Yc + 2;
407: xc += M2x * xstep;
408: yc += M2y * ystep;
409: break;
410: case 3:
411: Yc--;
412: delta -= 2 * Yc + 1;
413: xc += M3x * xstep;
414: yc += M3y * ystep;
415: break;
416: }
417: }
418: }
419:
420:
421: setsize(osize);
422: drawline((int)xc-ox1,(int)yc-oy1,".");
423: }
424:
425: putdot(x, y)
426: {
427: arcmove(x, y);
428: put1(drawdot);
429: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.