opengl 区域填充之种子填充线扫描法
青嵐影視 www.qldyy.net
在事先畫好的一個區域內,使用區域填充之種子填充線掃描法將其填充完畢。同時帶有鼠標和鍵盤事件,并添加了菜單。對于存在的改變窗口大小程序會出現問題還沒有很好的解決,只是僅僅將窗口大小固定住了,不能隨意改變大小。不對的地方,還請大家多多指正,希望與大家多交流哦。
#include <GL/glut.h>
#include <stdio.h>
//#include <conio.h>
//#include <dos.h>
#include <windows.h>
const int length = 3;
const int coord = 2;
const int num = 10;
int stack_top;
int stack[10000];
int fill = 0; /* fill flag */
// 長寬比受到限制,就現在而言只能是寬要大于長,原因有兩個,
//一個為(畫點)原點位置不正確,另一個是圍城區域的線條寬度太小
int Wheight = 200;
int Wwidth = 200;
int control = 0;
typedef float Color[length];
typedef int POI[coord];
Color newColor = {1.0f, 1.0f, 0};
// 背景顏色
Color oldColor = {1.0f, 0, 0};
// 函數調用前至少要先聲明,或者直接定義到掉用地之前
int stackPop()
{
?int val;
?val = stack[stack_top];
?stack_top = stack_top-1;
?return val;
}
void stackPush(int p_xy)
{
?stack_top += 1;
?stack[stack_top] = p_xy;
?
}
int isStackEmpty()
{
?if(stack_top>0)
??return 1;
?else
??return 0;
}
void setStackEmpty()
{
?int i;
?for(i=0; i<=stack_top; i++)
??stack[i]=0;
???? stack_top=0;
}
//畫點函數
void setPixel(float x, float y, Color color)
{
?glBegin(GL_POINTS);
?glColor3f(color[0], color[1], color[2]);
?glVertex2f(x, y);
?glEnd();
}
//顏色判定函數,顏色相同的話返回1,不相同的話則返回0
int judgeColor(float x, float y, Color color)
{
?Color tmp;
?int res = 1;
?glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, tmp);
?for (int i = 0; i < length; i++)
?{
??if(color[i] != tmp[i])
??{
???res = 0;
???//printf("%f,%f",x,y);
??}
?}
?return res;
}
// 填充函數(從最下側向上填充)
void floodFill(int x, int y, Color newColor, Color oldColor, int dir){
?int xl, xr, x0, xnextspan;
??? bool spanNeedFill;
??? //將棧清空
??? setStackEmpty();
??? //種子入棧
??? stackPush(x);
??? stackPush(y);
?while(isStackEmpty() != 0)
?{
??????? //棧頂出棧,注意出棧順序
??????? y = stackPop();
??????? x = stackPop();
??//printf("nihao1");
??????? setPixel(x, y, newColor);
??????? x0 = x+1;
??while(judgeColor(x0,y,oldColor) == 1) //向右填充
??{
???//printf("nihao2");
???setPixel(x0,y,newColor);
???x0++;
??}
??xr = x0-1;?//最右元素
??x0 = x-1;?//恢復到起始元素
??while(judgeColor(x0,y,oldColor) == 1) //向左填充
??{
???setPixel(x0, y, newColor);
???x0--;
??}
??xl=x0+1;?//最左元素
??//處理下面一條掃描線
??x0=xl;
??y=y+dir;
??if (isStackEmpty() == 0)
??{
??}
??// 從最左到最右均無oldColor元素將不再壓棧
??while (x0<=xr)
??{
???spanNeedFill=FALSE;
???
???while (judgeColor(x0,y,oldColor) == 1)
???{?
????if (spanNeedFill==FALSE)?
?????spanNeedFill=TRUE;
????x0++;
???}
???// 將元素壓棧
???if(spanNeedFill)
???{
????
????if (x0==xr)
????{
?????stackPush(x0);
?????stackPush(y);
????}
????else
????{
?????stackPush(x0-1);
?????stackPush(y);
????}
????spanNeedFill=FALSE;
???}
???xnextspan=x0;
???// 立即跳出循環
???while(judgeColor(x0,y,oldColor)!=1 && x0<xr) x0++;
???// 如果是最邊上的
???if (xnextspan==x0)
????x0++;
??}
?}
}
void drawLine()
{
?glBegin(GL_LINE_LOOP);
?glVertex2i(130, 130);
?glVertex2i(60, 130);
?glVertex2i(60, 10);
?glVertex2i(130, 10);
?glEnd();
?glFlush();
}
// 界面刷新
void refresh()
{
?glClearColor(1.0, 0.0, 0.0, 0.0);
?glClear(GL_COLOR_BUFFER_BIT);
?glFlush();
?drawLine();
}
void myDisplay(void)
{
?
?glClearColor(1.0, 0.0, 0.0, 0.0);
?glClear(GL_COLOR_BUFFER_BIT);
?// 單色方式
?glShadeModel(GL_FLAT);????
?// 設置點的大小
??? //glPointSize(100.0f);
?// 設置視口
?//glViewport(1.0f, 1.0f, 600, 400);
?glOrtho(-0.5f, Wwidth, -0.5f, Wheight, -200, 200);
?// 設置點的顏色
?glColor3f(0.0, 1.0f, 0.0f);
?glLineWidth(2);
??? //glBegin(GL_POINTS);
?// 繪制“點”的原點是在窗口正中間
?drawLine();
?//glPopAttrib();
}
// 鼠標左鍵事件
void mouse(int btn, int state, int x, int y)
{
?// x,y為窗口左上角為原點的鼠標位置
?if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
?{
??floodFill(x, Wheight-y, newColor, oldColor, 1);
??floodFill(x, Wheight-y, newColor, oldColor, -1);
??printf("開始填充");
??//printf("%d,\t%d",x,y);
?}
}
// 鼠標右鍵事件
void right_menu(int id)
{
?if(id == 2) exit(0);
?else if (id == 0)
?{
??floodFill(61, 129, newColor, oldColor, -1);
??printf("開始繪制");
?}
?else{
?//?myDisplay();
??refresh();
?}
}
// 鍵盤事件
void keyboard(unsigned char key, int x, int y)
{
?switch (key) {
?case 27:
??// Esc鍵退出
??exit(0);
??break;
?default:
??break;
??? }
}
/*
//換算比例
void changeSize(int w, int h) {
?
?// 防止除數即高度為0
?// (你可以設置窗口寬度為0).
?if(h == 0)
??h = 1;
?
?float ratio = 1.0* w / h;
?
?// 單位化投影矩陣。
?glMatrixMode(GL_PROJECTION);
?glLoadIdentity();
?
?// 設置視口大小為增個窗口大小
?glViewport(0, 0, w, h);
?
?// 設置正確的投影矩陣
?gluPerspective(45,ratio,1,1000);
?//下面是設置模型視圖矩陣
?glMatrixMode(GL_MODELVIEW);
?glLoadIdentity();
?gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0,0.0f,1.0f,0.0f);
}*/
?
void main()
{
?int f_menu;
?int gMainHandle;
?glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
??? glutInitWindowSize(Wwidth, Wheight);
??? glutInitWindowPosition(100, 150);?
??? gMainHandle = glutCreateWindow("Seed Fill");????
?glutSetWindow(gMainHandle);????
?HWND hwnd = FindWindow(NULL,"Seed Fill");????
?if( hwnd )????
?{????????
??LONG style;????????
??style = GetWindowLong(hwnd,GWL_STYLE);????????
??style &= ~WS_THICKFRAME;????????
??SetWindowLong(hwnd,GWL_STYLE,style);????
?}
?f_menu = glutCreateMenu(right_menu);
?glutAddMenuEntry("開始",0);
?glutAddMenuEntry("清空",1);
?glutAddMenuEntry("退出",2);
?glutAttachMenu(GLUT_RIGHT_BUTTON);
?glutMouseFunc(mouse);
?glutKeyboardFunc(keyboard);
??? glutDisplayFunc(&myDisplay);
?//換算比例
?//glutReshapeFunc(NULL);
?glutMainLoop();
}
轉載于:https://www.cnblogs.com/yxfcnbg/archive/2012/11/15/2772502.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的opengl 区域填充之种子填充线扫描法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Silverlight学习笔记(九)--
- 下一篇: sqlserver 中事务与错误机制的处