借鉴边缘填充算法,稍作修改。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;
}
运行结果如下: