青岚影视 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 区域填充之种子填充线扫描法相关推荐

  1. 13图形光栅化——区域填充(种子填充)+多边形扫描转换(扫描线算法)

    ♥,.*,.♥,.*,.♥,.*,.♥,.*♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥,.*,.♥♥,.*,.♥,.*,.♥,.*,.♥,.*♥,.*,.♥,.*,.♥ ...

  2. 【Algorithm】种子填充算法

    转载:https://www.cnblogs.com/icmzn/p/5065306.html [平面区域填充算法]是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界 (也可以是没有边 ...

  3. 【OpenGL C++】画一个空心汉字和一个圆,并填充汉字(中点画线法,中点画圆法,种子填充法)

    内容:画一个空心汉字和一个圆 设计一个画任意直线和圆的算法,可选所学的任一图形扫描转换算法(中点或bresenham算法),不能使用任何画线/画圆的API: 使用画线算法实现空心汉字的绘制,汉字必须为 ...

  4. 计算机图形学E4——OpenGL 区域种子填充

    其他计算机图形学实验见 链接 系统递归栈太慢了,用stack或者queue会好一点,本质一样,都是bfs //DFS 系统递归栈//#include<iostream> //#includ ...

  5. 多边形区域填充算法--扫描线种子填充算法

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow http://bl ...

  6. 区域填充:扫描线种子填充和剖面线填充

    #include "stdio.h" #include "graphics.h" #include "malloc.h" #include  ...

  7. 连通域分析之种子填充法

    一.连通域 需要了解连通域和两遍扫描法的可以看连通域分析之两遍扫描法(Two-Pass)这篇博文.我在里面已经介绍过了连通域的两种定义,这里就不再介绍.在此文中仍以4-邻域为例. 二.种子填充(区域填 ...

  8. c语言 连通域算法 递归,VC++ 6.0编写计算机图形学中的种子填充算法,想用递归的八向连通域,求助!...

    VC++ 6.0编写计算机图形学中的种子填充算法,想用递归的八向连通域,求助!0 填充函数代码如下: void CComputerGraphicsView::PolygonFill2()//区域填充函 ...

  9. matlab中种子填充算法

    因为作业要求用简单种子填充和线扫描填充,所以在网上找了一个用matlab写的简单种子填充算法. https://www.cnblogs.com/tiandsp/archive/2012/12/06/2 ...

最新文章

  1. MongoDB 3.4 复制集全量同步改进
  2. javascript去除首尾空白字符
  3. python三角形判断白盒测试的代码_进化的测试 软件测试,自动化测试,白盒测试,Python...
  4. Java调试器–权威的工具列表
  5. Python Configparser模块读取、写入配置文件
  6. Jackson第一篇【JSON字符串、实体之间的相互转换】
  7. Deal with relational data using libFM with blocks
  8. tcpdump高级过滤
  9. dhuacm出题网站搭建
  10. 6种摆脱百度竞价恶意点击的技巧
  11. VSCode无法跳转到外部函数定义
  12. xp安全模式下如何修复计算机,xp系统如何进入安全模式|进入安全模式修复系统...
  13. 安卓获取及监听手机网络状态
  14. XMind之快速上手
  15. psn请验证您不是机器人_PS4无法登陆PSN的解决办法
  16. 它来啦,它来啦!三子棋小游戏来啦!!!
  17. 2014-2015 少年辛苦终身事,莫向光阴惰寸功
  18. java中的this的用法_java中this的用法
  19. Memcache是什么
  20. 关于如何设置 Linux 的 IP配置

热门文章

  1. python具有伪代码的本质吗_Python的优点之一是具有伪代码的本质。( )_学小易找答案...
  2. C语言中return的各种用法
  3. html文档的基本类型,HTML(网页的文档类型介绍)
  4. 网络营销理论模型_网络营销:课堂笔记(第四章下)
  5. 光纤交换机产品功能介绍
  6. 工业级光纤收发器和协议转换器有什么区别呢?
  7. 百兆工业交换机与千兆工业交换机如何计算码率?
  8. 【渝粤教育】国家开放大学2018年春季 8634-22TAndroid智能手机编程 参考试题
  9. 【渝粤题库】广东开放大学 标准法律法规 形成性考核
  10. [渝粤题库]陕西师范大学《幼儿园社会教育》作业