边标志法填充多边形
這里不仔細講原理,只是把我寫的算法發出來,跟大家分享下,如果有錯誤的話,還請大家告訴我,如果寫的不好,也請指出來,一起討論進步。
基本思想: 先用一種特殊的顏色在幀緩沖器中將多邊形的邊界(水平邊界除外)勾畫出來,然后將著色的像素點依x坐標遞增的順序兩兩配對,再將每一對像素所構成的掃描線區間內的所有像素置為填充色。具體分為兩個步驟;
(1) 打標記。對多邊形的每條邊進行直線掃描轉換。
(2) 填充。 對每條與多邊形相交的掃描線,依從左到右順序,按“左閉右開”的原則對掃描線上的像素點進行填充。使用一個布爾量inside來指示當前點的狀態,若點在多邊形內,則inside為真,否則為假。inside初值為假,第當當前訪問像素為被打上標記的點時就把inside取反。對未打標記的像素,inside不變。若訪問當前像素時,對inside作必要操作后,inside為真,由把該像素置為填充色。
下面是程序:
/* * Date: 11/23/2010 */ #include <GL/glew.h> #include <GL/freeglut.h> #include <vector> #include <iostream> #include <fstream> using std::ofstream; using std::ifstream; using std::cout; using std::endl; ifstream cin ("polypoints.txt"); typedef struct _Point {int x;int y; }Point;typedef struct _PolyPoints {Point * pPoint; // Pointer to pointsint n; // Number of pointsint yMax; // Max y of all pointsint yMin; // Min y of all pointsint xMax; // Max x of all pointsint xMin; // Min x of all points }PolyPoints;PolyPoints g_polyPoints; // Storage for points of polygons bool ** g_pbEdgeFlag; // Edge flag void inputPoints (void) {int n;cin>>n;if (n < 3){cout<<"number of points can not be less than 3"<<endl;exit (0);}g_polyPoints.n = n;g_polyPoints.pPoint = new Point[n];g_polyPoints.yMax = INT_MIN;g_polyPoints.yMin = INT_MAX;g_polyPoints.xMax = INT_MIN;g_polyPoints.xMin = INT_MAX;int x, y;for (int i = 0; i < n; ++i){cin>>x>>y;g_polyPoints.pPoint[i].x = x;g_polyPoints.pPoint[i].y = y;if (g_polyPoints.yMax < y){g_polyPoints.yMax = y;}if (g_polyPoints.yMin > y){g_polyPoints.yMin = y;}if (g_polyPoints.xMax < x){g_polyPoints.xMax = y;}if (g_polyPoints.xMin > x){g_polyPoints.xMin = x;}}int xLen = g_polyPoints.xMax - g_polyPoints.xMin + 1;int yLen = g_polyPoints.yMax - g_polyPoints.yMin + 1;g_pbEdgeFlag = new bool *[yLen];for (int i = 0; i < yLen; ++i){g_pbEdgeFlag[i] = new bool [xLen];memset (g_pbEdgeFlag[i], 0, sizeof (bool) * xLen);} } // Free the memory void destroy (void) {int yLen = g_polyPoints.yMax - g_polyPoints.yMin + 1;for (int i = 0; i < yLen; ++i){delete g_pbEdgeFlag[i];}delete g_pbEdgeFlag;} void scanConvertLineAndFlag (const Point & p1, const Point & p2) {int x1 = p1.x;int y1 = p1.y;int x2 = p2.x;int y2 = p2.y;int x, y, dx, dy, e;// k does not existif (x1 == x2){if (y1 < y2){y = y1;glBegin (GL_POINTS);while (y <= y2){glVertex2i (x1, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x1-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x1-g_polyPoints.xMin] = !bFlag;++ y;}glEnd ();} // if (y1 < y2)else{y = y2;glBegin (GL_POINTS);while (y <= y1){glVertex2i (x1, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x1-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x1-g_polyPoints.xMin] = !bFlag;++ y;}glEnd ();}} // if (x1 == x2)else if (y1 == y2) // k = 0{if (x1 < x2){glBegin (GL_POINTS);x = x1;while (x <= x2){glVertex2i (x, y1);++ x;}glEnd ();} // if (x1 < x2)else {x = x2;glBegin (GL_POINTS);while (x <= x1){glVertex2i (x, y1);++ x;}glEnd ();}}else {if (x1 > x2){int temp = x1;x1 = x2;x2 = temp;temp = y1;y1 = y2;y2 = temp;}x = x1;y = y1;dx = x2 - x1;dy = y2 - y1;// k = 1if (dx == dy){glBegin (GL_POINTS);while (x <= x2){glVertex2i (x, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin] = !bFlag;++ x;++ y;}glEnd ();}else if (dx == -dy) // k = -1{glBegin (GL_POINTS);while (x <= x2){glVertex2i (x, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin] = !bFlag;++ x;-- y;}glEnd ();}else if (dy > dx) // k > 1{glBegin (GL_POINTS);dx <<= 1;e = - dy;dy <<= 1;y = y1 > y2 ? y2 : y1;int maxY = y1 > y2 ? y1 : y2;while (y <= maxY){glVertex2i (x, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin] = !bFlag;++ y;e += dx;if (e > 0){++ x;e -= dy;}}glEnd ();}else if (dy > 0) // 0 < k < 1{e = -dx;dx <<= 1;dy <<= 1;glBegin (GL_POINTS);while (x <= x2){glVertex2i (x, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin] = !bFlag;++ x;e += dy;if (e > 0){e -= dx;++ y;}}glEnd ();}else if (-dy < dx) // 0 > k > -1{e = -dx;dx <<= 1;dy <<= 1;glBegin (GL_POINTS);while (x <= x2){glVertex2i (x, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin] = !bFlag;++ x;e += dy;if (e < 0){-- y;e += dx;}}glEnd ();}else if (-dy > dx) // k < -1{e = dy;dx <<= 1;dy <<= 1;glBegin (GL_POINTS);y = y1 > y2 ? y1 : y2;int minY = y1 > y2 ? y2 : y1;while (y >= minY){glVertex2i (x, y);// Flag current pointbool bFlag = g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin];g_pbEdgeFlag[y-g_polyPoints.yMin][x-g_polyPoints.xMin] = !bFlag;e += dx;-- y;if (e > 0){++ x;e += dy;}}glEnd ();}} } void init (void) {glClearColor (0.0f, 0.0f, 0.0f, 1.0f); }void flagAllEdges (void) {Point * pPoint = g_polyPoints.pPoint;int n = g_polyPoints.n;for (int i = 0; i < n; ++ i){scanConvertLineAndFlag (pPoint[i], pPoint[(i+1)%n]);}for (int i = 0; i < n; ++i){int j1 = (i+n-1)%n;int j2 = (i+1)%n;if (pPoint[j1].y > pPoint[i].y && pPoint[j2].y > pPoint[i].y ||pPoint[j1].y < pPoint[i].y && pPoint[j2].y < pPoint[i].y){g_pbEdgeFlag[pPoint[i].y - g_polyPoints.yMin][pPoint[i].x - g_polyPoints.xMin] = false;}else{g_pbEdgeFlag[pPoint[i].y - g_polyPoints.yMin][pPoint[i].x - g_polyPoints.xMin] = true;}} }void edgeFlagFillPolygon (void) {int xLen = g_polyPoints.xMax - g_polyPoints.xMin + 1;int yLen = g_polyPoints.yMax - g_polyPoints.yMin + 1;int nScanLine = g_polyPoints.yMin;glBegin (GL_POINTS);for (int i = 0; i < yLen; ++i, ++ nScanLine){bool bFlag = false;int nHorizontal = g_polyPoints.xMin;for (int j = 0; j < xLen; ++j, ++ nHorizontal){if (g_pbEdgeFlag[i][j]){bFlag = !bFlag;}while (bFlag){glVertex2i (nHorizontal, nScanLine);++ j;++ nHorizontal;if (g_pbEdgeFlag[i][j]){bFlag = !bFlag;}}}}glEnd ();}void display (void) {glClear (GL_COLOR_BUFFER_BIT);glLoadIdentity ();glColor3f (1.0f, 0.0f, 0.0f);//flagAllEdges ();// Fill a polygonedgeFlagFillPolygon ();glutSwapBuffers (); }void reshape (int w, int h) {glViewport (0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode (GL_PROJECTION);glLoadIdentity ();if (w <= h){gluOrtho2D (-600.0, 600.0, -600.0 * (GLfloat) h / (GLfloat) w, 600.0 * (GLfloat) h / (GLfloat) w);}else{gluOrtho2D (-600.0 * (GLfloat) w / (GLfloat) h,600.0 * (GLfloat) w / (GLfloat) h, -600.0, 600.0);}glMatrixMode (GL_MODELVIEW);glLoadIdentity (); } void keyboard (unsigned char key, int x, int y) {switch (key){case 27: // 'VK_ESCAPE'exit (0);break;default:break;} } int main (int argc, char ** argv) {glutInit (&argc, argv);glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);glutInitWindowSize (600, 600);glutCreateWindow ("Bresenham line");init ();inputPoints ();flagAllEdges ();glutReshapeFunc (reshape);glutDisplayFunc (display);glutKeyboardFunc (keyboard);glutMainLoop ();destroy ();return 0; } polypoints.txt中的示例內容如下: 7 30 120 10 70 30 10 60 50 80 10 120 90 70 80
轉載于:https://www.cnblogs.com/ghl_carmack/archive/2010/12/04/1896644.html
總結
- 上一篇: Eclipse编写Java程序
- 下一篇: 年龄大了学Java是爱好还是转型?