|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24: /* $Header: mipolycon.c,v 1.15 87/09/11 07:18:54 toddb Exp $ */
25: #include "gcstruct.h"
26: #include "pixmap.h"
27: #include "miscanfill.h"
28:
29: /*
30: * convexpoly.c
31: *
32: * Written by Brian Kelleher; Dec. 1985.
33: *
34: * Fill a convex polygon. If the given polygon
35: * is not convex, then the result is undefined.
36: * The algorithm is to order the edges from smallest
37: * y to largest by partitioning the array into a left
38: * edge list and a right edge list. The algorithm used
39: * to traverse each edge is an extension of Bresenham's
40: * line algorithm with y as the major axis.
41: * For a derivation of the algorithm, see the author of
42: * this code.
43: */
44: void
45: miFillConvexPoly(dst, pgc, count, ptsIn)
46: DrawablePtr dst;
47: GCPtr pgc;
48: int count; /* number of points */
49: DDXPointPtr ptsIn; /* the points */
50: {
51: register int xl, xr; /* x vals of left and right edges */
52: register int dl, dr; /* decision variables */
53: register int ml, m1l; /* left edge slope and slope+1 */
54: int mr, m1r; /* right edge slope and slope+1 */
55: int incr1l, incr2l; /* left edge error increments */
56: int incr1r, incr2r; /* right edge error increments */
57: int dy; /* delta y */
58: int y; /* current scanline */
59: int left, right; /* indices to first endpoints */
60: int i; /* loop counter */
61: int nextleft, nextright; /* indices to second endpoints */
62: DDXPointPtr ptsOut, FirstPoint; /* output buffer */
63: int *width, *FirstWidth; /* output buffer */
64: int imin; /* index of smallest vertex (in y) */
65: int ymin; /* y-extents of polygon */
66: int ymax;
67:
68: /*
69: * find leftx, bottomy, rightx, topy, and the index
70: * of bottomy. Also translate the points.
71: */
72: imin = getPolyYBounds(ptsIn, count, &ymin, &ymax);
73:
74: dy = ymax - ymin + 1;
75: ptsOut = FirstPoint = (DDXPointPtr )ALLOCATE_LOCAL(sizeof(DDXPointRec)*dy);
76: width = FirstWidth = (int *)ALLOCATE_LOCAL(sizeof(int) * dy);
77: if(!ptsOut || !width)
78: {
79: DEALLOCATE_LOCAL(width);
80: DEALLOCATE_LOCAL(ptsOut);
81: return;
82: }
83:
84: if ((count < 3) || (dy < 0))
85: {
86: DEALLOCATE_LOCAL(width);
87: DEALLOCATE_LOCAL(ptsOut);
88: return;
89: }
90:
91: nextleft = nextright = imin;
92: y = ptsIn[nextleft].y;
93:
94: /*
95: * loop through all edges of the polygon
96: */
97: do {
98: /*
99: * add a left edge if we need to
100: */
101: if (ptsIn[nextleft].y == y) {
102: left = nextleft;
103:
104: /*
105: * find the next edge, considering the end
106: * conditions of the array.
107: */
108: nextleft++;
109: if (nextleft >= count)
110: nextleft = 0;
111:
112: /*
113: * now compute all of the random information
114: * needed to run the iterative algorithm.
115: */
116: BRESINITPGON(ptsIn[nextleft].y-ptsIn[left].y,
117: ptsIn[left].x,ptsIn[nextleft].x,
118: xl, dl, ml, m1l, incr1l, incr2l);
119: }
120:
121: /*
122: * add a right edge if we need to
123: */
124: if (ptsIn[nextright].y == y) {
125: right = nextright;
126:
127: /*
128: * find the next edge, considering the end
129: * conditions of the array.
130: */
131: nextright--;
132: if (nextright < 0)
133: nextright = count-1;
134:
135: /*
136: * now compute all of the random information
137: * needed to run the iterative algorithm.
138: */
139: BRESINITPGON(ptsIn[nextright].y-ptsIn[right].y,
140: ptsIn[right].x,ptsIn[nextright].x,
141: xr, dr, mr, m1r, incr1r, incr2r);
142: }
143:
144: /*
145: * generate scans to fill while we still have
146: * a right edge as well as a left edge.
147: */
148: i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y;
149: /* in case we're called with non-convex polygon */
150: if(i < 0)
151: {
152: DEALLOCATE_LOCAL(FirstWidth);
153: DEALLOCATE_LOCAL(FirstPoint);
154: return;
155: }
156: while (i-- > 0)
157: {
158: ptsOut->y = y;
159:
160: /*
161: * reverse the edges if necessary
162: */
163: if (xl < xr)
164: {
165: *(width++) = xr - xl;
166: (ptsOut++)->x = xl;
167: }
168: else
169: {
170: *(width++) = xl - xr;
171: (ptsOut++)->x = xr;
172: }
173: y++;
174:
175: /* increment down the edges */
176: BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
177: BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
178: }
179: } while (y != ymax);
180:
181: /*
182: * Finally, fill the <remaining> spans
183: */
184: (*pgc->FillSpans)(dst, pgc,
185: ptsOut-FirstPoint,FirstPoint,FirstWidth,
186: 1);
187: DEALLOCATE_LOCAL(FirstWidth);
188: DEALLOCATE_LOCAL(FirstPoint);
189: }
190:
191:
192: /*
193: * Find the index of the point with the smallest y.
194: */
195: static
196: int
197: getPolyYBounds(pts, n, by, ty)
198: DDXPointPtr pts;
199: int n;
200: int *by, *ty;
201: {
202: register DDXPointPtr ptMin;
203: int ymin, ymax;
204: DDXPointPtr ptsStart = pts;
205:
206: ptMin = pts;
207: ymin = ymax = (pts++)->y;
208:
209: while (--n > 0) {
210: if (pts->y < ymin)
211: {
212: ptMin = pts;
213: ymin = pts->y;
214: }
215: if(pts->y > ymax)
216: ymax = pts->y;
217:
218: pts++;
219: }
220:
221: *by = ymin;
222: *ty = ymax;
223: return(ptMin-ptsStart);
224: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.