计算机图形学 栅栏填充算法 C++

借鉴边缘填充算法,稍作修改。C++代码如下:

#include <GL/glut.h>
#include <math.h>
#include <iostream>
using namespace std;

//算法全局变量
GLint point[13][2]; //顶点坐标
int points;//顶点个数
int PointSex[10];//顶点的特性:局部最高点,局部最低点,过度点(中间点)
int ix=-1;//鼠标事件1 选择下一条线段绘制
int beginlc=0;//鼠标事件2 开始标志
int pointColor[300][300];
/顶点编辑阶段
//界面1,输入多边形
void selectpoint()
{
 cout<<"输入多边形顶点个数(小于10):  ";
 cin>>points;
 for(int i=0;i<points;i++)
{
 cout<<"这是第 "<<i+1<<" 个顶点:\n";
for(int j=0;j<2;j++)
{
 cin>>point[i][j];
} 
} 
/*测试用例 
points=5;
point[0][0]=110;
point[0][1]=10;

point[1][0]=250;
point[1][1]=60;

point[2][0]=280;
point[2][1]=180;

point[3][0]=170;
point[3][1]=140;

point[4][0]=120;
point[4][1]=250;*/
//}
cout<<"右击开始"<<endl;

}

//顶点属性
void DecidePointSex(int pointsno)
{
int i=(pointsno-1)%points;
if(i==-1) i=points-1;
int j=(pointsno+1)%points;
GLint BeforeY=point[i][1];//前一个点Y值
GLint NextY=point[j][1];//后一个点Y值
if((point[pointsno][1] < BeforeY) && (point[pointsno][1] < NextY)) PointSex[pointsno]=1;//类型1,最低点
else if(point[pointsno][1]>BeforeY&&point[pointsno][1]>NextY) PointSex[pointsno]=2;//类型2,最高点
else PointSex[pointsno]=3;//类型3,过度点
}
算法阶段/
//当前点所在行涂色

void PrintOneLine(GLint x, GLint y)
{
GLint left,right;
if(x>=point[points][0])
{
left=point[points][0];
right=x;
}
else
{
left=x;
right=point[points][0];
}


for(int i=left;i<=right;i++)
{
switch (pointColor[i][y])//涂色模式
{
case 0://正常涂色
{
glBegin(GL_POINTS);//画点
glColor3f(0.4,0.2,0.8);
glVertex2i (i,y);
glEnd();
pointColor[i][y]=1;//取反
break;
}//蓝色
case 1://涂底色
{
glBegin(GL_POINTS);
glColor3f(0.0,0.0,0.0);
glVertex2i (i,y);
glEnd();
pointColor[i][y]=0;//取反
break;
}//黑色
}

}
}


//通过Bresenham算法找到像素点并涂色 
void BresenhamSetLine(GLint x1,GLint y1,GLint x2,GLint y2)
{
cout<<"++++++++Bresenham++++++++++"<<endl;
int x=x1,y=y1;
int dx=abs(x2-x1),dy=abs(y2-y1);
int s1 = x2>x1 ? 1 : -1;//x轴步进
int s2 = y2>y1 ? 1 : -1;//y轴步进
bool Change=false;//通过斜率判断,交换步进方式
if(dy>dx)//斜率k>1,dx dy 交换
{
int t=dx;dx=dy;dy=t;
Change=true;
}
int p=2*dy-dx;
///执行阶段----先选点再前进,p无论是否选点一定会+2dy。change判断方向,s1s2判断前后。
for(int kk=0;kk<dx;kk++)
{
cout<<"No="<<kk<<" x="<<x<<" y="<<y;
//选点
if(p>=0)
{
if(!Change)//k<1 选择上下点
{
y+=s2;
PrintOneLine(x,y);//如果步进方式为沿x轴,2个相邻点y值可能相同,则取变化点。
}
else//k>1 选择左右点
{
x+=s1;
}
p-=2*dx;//p在原基础(+2dy)上-2dx
}


//前进
if(!Change)//k<1 x轴为步进方向
{x+=s1;}
else//k>1 y轴为步进方向
{
 y+=s2;
 PrintOneLine(x,y);//如果步进方式为沿y轴,正常输出每一行。
}
p+=2*dy;//无论p是否大于0,都执行+2dy操作;简化步骤
 cout<<" Next pointColor="<<pointColor[x+1][y]<<endl;
 }
}

//沿边涂色动画辅助函数
void linechoose(int i)
{
 int j=(i+1)%points;
 BresenhamSetLine(point[i][0],point[i][1],point[j][0],point[j][1]);//不画最后一点
if(PointSex[j]==1||PointSex[j]==2) PrintOneLine(point[j][0],point[j][1]);
}

void drawzl()//确定栅栏的位置
{
 cout<<"请输入栅栏经过的一个顶点坐标:";
 cin>>point[points][0];
 cin>>point[points][1];
 point[points+1][0]=point[points][0];
 point[points+1][1]=1000;
 point[points+2][0]=point[points][0];
 point[points+2][1]=-1000;
}

void display(void)
{
 glViewport(50,50,300,300);  //视口位置大小
 glBegin(GL_LINE_LOOP);//显示多边形图案
for(int i=0;i<points;i++)
{
 glColor3f (1.0 ,1.0, 1.0);
 glVertex2iv (point[i]);
}
 glEnd();


 glBegin(GL_LINES);//显示栅栏
 glVertex2iv(point[points+1]);
 glVertex2iv(point[points+2]);
 glEnd();


if (beginlc==1&&ix>=0)//点击开始
{
 linechoose(ix);
}


 glFlush ();
}


void init (void) 
{ 
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,300,0,300);
glMatrixMode(GL_MODELVIEW);
}


void mouse(int btn, int state, int x, int y)
{ 
if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN && beginlc == 1)
{

ix=(ix+1);//换边
if(ix>=points) {beginlc = 0;}//不允许操作
glutPostRedisplay();//窗口重绘

}
if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
beginlc=1;cout<<"start";
}
}

int main(int argc, char** argv)
{
for(int i=0;i<300;i++)
{
for(int j=0;j<300;j++)
{
{pointColor[i][j]=0;}
}
}//初始化标志数组
selectpoint();
for(i=0;i<points;i++)
{
DecidePointSex(i);
}//根据属性分类顶点
drawzl();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (400, 400); 
glutInitWindowPosition (500, 100);
glutCreateWindow ("hello");
init();
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMainLoop();

return 0;
}



运行结果如下:





  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值