扫描线--通用多边形填充算法
扫描线--通用多边形填充算法 该算法有几个可学习的地方: (1)正负1思想 (2)对边界条件的处理 (3)数据结构的选择 code: sweep.h #ifndef SWEEP_H #define SWEEP_H struct Edge { int nxty; int curx; int dx, dy; // 所在扫描线的增量 Edge nxt; }; //扫描线主算法 void sweep(int p[][2], int n, void (setPixel)(int, int)); #endifsweep.cpp #include “sweep.h” #include <algorithm> using namespace std; const int MAXN = 1024; int cp[MAXN][2], n; inline bool cmp(int i, int j) { return cp[i][1] < cp[j][1] |
(cp[i][1] == cp[j][1] && cp[i][0] < cp[j][0]); } Edge * e[MAXN], *h, *ph, *data; void insert(int ly, int px, int ind) { int y1,y2,y, nxt, pre, flag=0; nxt = (ind + 1) % n; pre = (ind - 1 + n) % n; y = cp[ind][1]; y1 = cp[nxt][1]; y2 = cp[pre][1]; if (y1 > y2) swap(y1, y2); if (y1 < y && y < y2) { //需缩短一个单位 flag = 1; } h = e[ly]; ph=NULL; while (h) { if (h->dy > cp[ind][1] |
(h->dy == cp[ind][1] && h->dx > cp[ind][0])) break; ph = h; h = h->nxt; } data = new Edge; data->curx = px; data->nxty = cp[ind][1]; data->dx = cp[ind][0] - px; data->dy = cp[ind][1] - ly; data->nxt = NULL; if (flag) data->nxty–; if (ph) { data->nxt = ph->nxt; ph->nxt = data; } else { data->nxt = e[ly]; e[ly] = data; } } int ex[MAXN][MAXN], ne[MAXN]; inline int abs(int a) { return a > 0 ? a : -a; } void makepoint(int line, Edge h) { int dx = h->dx, dy = h->dy, cnt=0; int x, y, flag=1; if ((h->dx)(h->dy)<0) flag=0; for (y=line, x=h->curx; y<=h->nxty; y++) { ex[y][ne[y]++] = x; cnt += 2abs(dx); while (cnt>=2abs(dy)) { cnt -= 2abs(dy); if (flag) x++; else x–; } } } void sweep(int p[][2], int nn, void (setPixel)(int, int)) { //对所有点按y坐标递增排序,y坐标相等的按x坐标递增排序 n = nn; int i, j, k, ind, nxt, pre; int *num = new int[n]; //点索引; for (i=0; i<n; i++) num[i] = i; memcpy(cp, p, sizeof(cp)); sort(num, num+n, cmp); //建立有序边表 memset(e, 0, sizeof(e)); for (i=0; i<n; i++) { ind = num[i]; nxt = (ind + 1) % n; pre = (ind - 1 + n) % n; if (p[nxt][1] > p[ind][1]) insert(p[ind][1], p[ind][0], nxt); if (p[pre][1] > p[ind][1]) insert(p[ind][1], p[ind][0], pre); } //处理active edge list memset(ne, 0, sizeof(ne)); for (i=0; i<MAXN; i++) { h = e[i]; ph = NULL; while (h) { makepoint(i, h); h = h->nxt; } sort(ex[i], ex[i]+ne[i]); for (j=0; j<ne[i]; j+=2) for (k=ex[i][j]; k<=ex[i][j+1]; k++) setPixel(k,i); } }sweepline.cpp #include <stdlib.h> #include <stdio.h> #include <GL/glut.h> #include “sweep.h” void myInit(); void setPixel(int x, int y); void myDisplay(); int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE |
GLUT_RGB); glutInitWindowSize(640, 480); glutInitWindowPosition (100, 150); glutCreateWindow(“SweepLine”); glutDisplayFunc(myDisplay); myInit(); glutMainLoop(); return 0; } void setPixel(int x, int y) { glBegin(GL_POINTS); glVertex2i(x, y); glEnd(); } void myInit() { glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 640.0, 0.0, 480.0); } void myDisplay() { int i, j; glClear(GL_COLOR_BUFFER_BIT); int p[5][2]; p[0][0] = 100; p[0][1] = 300; p[1][0] = 200; p[1][1] = 50; p[2][0] = 300; p[2][1] = 100; p[3][0] = 400; p[3][1] = 0; p[4][0] = 350; p[4][1] = 470; sweep(p, 5, setPixel); glFlush(); } http://zhidao.baidu.com/question/40582214.html |