zoukankan      html  css  js  c++  java
  • 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();
    }

  • 相关阅读:
    2016年3月17日----Javascript的正则表达式
    2016年3月17日----Javascript的时间与日期
    2016年3月9日----Javascript的对象和数组
    2016年3月8日----Javascript的函数
    2016年3月7日----Javascript的运算符
    2016年3月7日----Javascript的数据类型
    2016年3月1日----Javascript的数组元素的添加、移除以及其他常用方法
    console深入理解
    浏览器特性和安全策略
    每日新知
  • 原文地址:https://www.cnblogs.com/yxfcnbg/p/2772502.html
Copyright © 2011-2022 走看看