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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React 篇 Search Bar and content Table

我们要构建一个模块&#xff0c;其中包含一个内容显示的表格&#xff0c;然后上面有一个提供Search的栏位&#xff0c;并对Search中输入栏进行监听&#xff0c;当有改变的时候&#xff0c;触发Search然后对内容表中的内容进行过滤。 Demo Link:http://czrmodel.mybluemix.net/…

PrimeFaces:在动态生成的对话框中打开外部页面

我已经在即将出版的PrimeFaces Cookbook 2版中写了一篇关于食谱的博客。 在这篇文章中&#xff0c;我想发表第二篇关于一个名为Dialog Framework的小型框架的文章。 我个人喜欢它&#xff0c;因为我记得我为使用Struts框架付出同样的努力而付出的代价。 当您想将外部页面加载到…

ctags: 提示错误ctags: unrecognized option '--format=2'

ctags&#xff1a; 提示错误ctags: unrecognized option --format2 原来的 taglist 插件用的好好的&#xff0c;自从安装了 emacs 之后&#xff0c;每次触发 taglist 都提示以下错误&#xff1a; Taglist: Failed to generate tags for ....(a file) ctags: unrecognized optio…

vue-router之 beforeRouteEnter

beforeRouteEnter在每次路由切换都执行 ,而项目优化后,切换路由mounted只在最开始执行一次beforeRouteEnter的具体用法可参考官方文档 https://cn.vuejs.org/v2/guide/migration-vue-router.html#activate-替换 需要注意的是&#xff1a;在这期间路由跳转携带的数据发生改变会影…

突破极限–如何将AeroGear Unified Push用于Java EE和Node.js

在2014年底的AeroGear队宣布红帽的JBoss统一推送服务器的可用性xPaaS 。 让我们仔细看看&#xff01; 总览 统一推送服务器允许开发人员将本地推送消息发送到Apple的推送通知服务&#xff08;APNS&#xff09;和Google的云消息传递&#xff08;GCM&#xff09;。 它具有一个内…

sqlserver 中事务与错误机制的处理

成功返回1并提交事务,错误返回0并回滚事务 BEGIN try begin tran --其中userName为varchar类型,数据库中该字段存在不为int类型的数据,必然导致错误 update WebOA_User_t SET UserNameUserName where UserName1 select 1 commit tran end try begin catch select 0 r…

js 获取json数组里面数组的长度

作为一个前端页面开发者第一次处理json数据&#xff0c;遇到了‘js 获取json数组里面数组的长度’&#xff1f;竟然不知道 json没有.length属性&#xff08;真是要嘲讽下自己&#xff09;&#xff0c;少壮不努力老大徒伤悲啊&#xff01;以前都是去寻求男朋友帮助&#xff0c;但…

针对WildFly和EAP运行Java Mission Control和Flight Recorder

Java Mission Control &#xff08;JMC&#xff09;使您可以监视和管理Java应用程序&#xff0c;而无需引入通常与这些类型的工具相关的性能开销。 它使用为正常的JVM动态优化而收集的数据&#xff0c;从而形成了一种非常轻量级的方法来观察和分析应用程序代码中的问题。 JMC由…

C#堆栈和堆的讲解

OS和CLR通常将用于容纳数据的内存划分为两个独立的区域&#xff0c;每个区域都采用截然不同的方式来管理&#xff1a;堆栈&#xff08;Stack&#xff09;和堆&#xff08;heap&#xff09;。&#xff08;1&#xff09; 调用一个方法时&#xff0c;它的参数以及它的局部变…

jQuery中的常用内容总结(一)

jQuery中的常用内容总结(一) 前言 不好意思(✿◠‿◠)&#xff0c;由于回家看病以及处理一些其它事情耽搁了&#xff0c;不然这篇博客本该上上周或者上周写的&#xff1b;同时闲谈几句&#xff1a;在这里建议各位开发的童鞋&#xff0c;如果有疾病尽快治疗&#xff0c;不要拖&a…

关于Firefox在Win8下界面显示错乱的解决方法

最近又把Windows8安装上&#xff0c;由于平常做前端开发用的最多的还是Firefox&#xff0c;因此在家的机器上也安装上Firefox&#xff0c;但使用中发现Firefox界面老是错误&#xff0c;特别是那种乱套的颜色&#xff0c;不得其解&#xff0c;查看设置发现默认启用了硬件加速&am…

react ant design路由配置

最初的时候&#xff0c;只使用了antd中的menu&#xff0c;header和footer都是自己写的组件&#xff0c;在写路由时&#xff0c;总是报如下错误&#xff1a; 相关的路由配置如下&#xff1a; 在网上查的说是组件未暴露出去或者是return 这一行必须有个括号或者标签&#xff0c;我…

线程魔术技巧:Java线程可以做的5件事

Java线程最鲜为人知的事实和用例是什么&#xff1f; 有些人喜欢爬山&#xff0c;有些人喜欢跳伞。 我&#xff0c;我喜欢Java。 我喜欢它的一件事是&#xff0c;您永不停止学习。 您每天使用的工具通常可以向您展示全新的方面&#xff0c;以及您还没有机会看到的方法和有趣的用…

强制删除tfs未迁入项的两个方法。

方法1&#xff1a; 打开Vs2008的命令提示&#xff1a; 查看用户的工作区&#xff1a; 输入&#xff1a; Tf workspaces /owner:所有者或* /server:服务器名称或IP ex: tf workspaces /owner:stcct(所有者) /server:203.156.1.100(Ip地址) 删除用户的未迁入项&#xff1a; 输…

VUE 全选

<div id"vue_det"> <p>全选:</p> <input type"checkbox" id"checkbox" v-model"checked" change"changAllChecked"/> <label for"checkbox"> {{checked}} <…

RabbitMQ –使用Spring集成Java DSL串行处理消息

如果您曾经需要使用RabbitMQ来串行处理消息&#xff0c;并且有一群监听器来处理消息&#xff0c;那么我所看到的最好方法是在监听器上使用“独占消费者”标志&#xff0c;每个监听器上有1个线程来处理消息。 专用使用者标志可确保只有1个使用者可以从特定队列中读取消息&#…

添加删除约束脚本 ::fn_get_sql

添加约束&#xff1a;alter table table1 add constraint pk_name primary key (name) --添加主健约束,名称作为主健&#xff1b; alter table table1 add constraint pk_name unique (name) --添加唯一约束,…

jquery 实现 点击把数据移动右侧 点击再次移回到左侧

2018年第一发 希望新的一年和大家一下学习更多知识 JS&#xff1a;//把数据左边挪到了右边&#xff0c;再从右边移动回来function moveOption(e1, e2){ $("#" e1 " option").each(function(){ if($(this).is(:selected)){ var oVal…

企业Java中事务隔离级别的初学者指南

介绍 基于ACID事务属性的关系数据库强一致性模型。 在本文中&#xff0c;我们将阐明对资源本地事务和JTA事务使用不同的事务隔离级别和各种配置模式的背后原因。 隔离和一致性 在关系数据库系统中&#xff0c;原子性和持久性是严格的属性&#xff0c;而一致性和隔离性或多或少…

点击左侧跳到右侧

效果图 JS部分 function moveOption(e1, e2){ try{ for(var i0;i<e1.options.length;i ){ if(e1.options[i].selected){ var e e1.options[i]; e2.options.add(new Option(e.text, e.value)); e1.remove(i); iii-1 } } } catch(e){}} HTML以及CSS部分 <for…