计算机图形学课程设计报告.docx
《计算机图形学课程设计报告.docx》由会员分享,可在线阅读,更多相关《计算机图形学课程设计报告.docx(14页珍藏版)》请在冰豆网上搜索。
计算机图形学课程设计报告
《计算机图形学》
课程设计报告
题目:
用画笔交互绘制任意封闭区域,并可选不同的颜色填充
姓名:
学号:
班级:
专业:
计算机科学与技术
指导教师:
完成时间:
2014年6月8日
目录
系统功能设计:
3
详细设计:
3
关键代码:
4
<1>中点画圆法:
4
<2>绘制多边形:
5
<3>扫描线种子填充代码:
5
<4>清屏代码:
9
实验结果:
9
画笔、RGB值均为零:
9
画笔宽度设置为2且RGB值不同:
10
遇到问题与解决方法:
11
总结与展望:
11
系统功能设计:
用画笔交互绘制任意封闭区域,由于圆和多边形的画法不同,所以需要制定两个按钮用来画圆和多边形,再添加一个按钮来实现填充功能。
为比较扫描线种子填充和扫描线填充的差异,本次课程设计用种子算法填充圆形,用扫描线填充任意多边形,要求实现可选不同颜色填充,则需要用四个编辑框,三个编辑框来控制RGB的值,另外一个控制画笔宽度,从而调用用户输入的画笔宽度值及RGB值实现交互控制画笔宽度和封闭区域颜色的填充。
详细设计:
<1>创建单文本对话框,编辑菜单栏“图形学”,创建子菜单“课程设计”,选中“课程设计”创建对话框,添加按钮,编辑框,静态文本后修改属性,进入编辑界面。
<2>添加类向导,OnLButtonDown和OnLButtonup,通过OnLButtonDown函数获取鼠标按下时的X坐标和Y坐标,并把坐标赋值给数组x[],y[],通过OnLButtonUp函数获取鼠标弹起是的坐标赋值给xe,ye,为画圆和画多边形的做准备。
<3>双击画圆按钮,用中点画圆算法编写相关画圆代码。
用中点画圆法通过比较两点间d的值来取相近点,然后用打点的方法连接所有点,具体参考书上代码
<4>双击多边形按钮,用画线连接编写相关画多边形代码。
用数组存储获取的鼠标点的坐标,然后点以一个变量,比较鼠标点的最大最小值,从而确定边界,然后确定扫描线算法动态链接各个点。
<5>双击填充按钮,用扫描线种子填充算法编写填充代码。
在获取鼠标点之后,获取存储在数组中的数据,然后以该点为圆心和种子节点,用种子填充算法开始进行相关进站出站操作,然后对相关像素点进行染色,从而实现圆的颜色填充。
多边形的填充是通过调用windows中的画笔,在多边形的各个边都确定了以后,对原像素进行画笔像素覆盖,而实现各种颜色的填充。
<6>双击清屏按钮,用清除函数实现清屏功能。
对于数组中的值以及鼠标点击后的赋予变量的值都进行重新赋值为零的操作,实现已实现的数据代码置零操作。
<7>RGB的文本框用UpdataData(true)实现。
对于各个文本框进行变量绑定,在程序中通过调用绑定的各个文本框变量实现文本框RGB值的更新,实现颜色的变换操作。
关键代码:
<1>中点画圆法:
voidCyuan:
:
OnButton1()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
CDC*pDC=GetDC();
intx0=xs;
inty0=ys;
intr=(int)sqrt((xs-xe)*(xs-xe)+(ys-ye)*(ys-ye));
intf,b,d,x,y;
d=1-r;x=0;y=r;//r为圆的半径
while(y>=x)
{
for(f=-m;f<=m;f++)
{
for(b=-m;b<=m;b++)
{
pDC->SetPixel(x0,y0,RGB(w,n,s));
pDC->SetPixel(x+x0+f,y+y0+b,RGB(w,n,s));//(x0,y0)为圆心坐标
pDC->SetPixel(-x+x0+f,y+y0+b,RGB(w,n,s));
pDC->SetPixel(-x+x0+f,-y+y0+b,RGB(w,n,s));
pDC->SetPixel(x+x0+f,-y+y0+b,RGB(w,n,s));
pDC->SetPixel(y+x0+f,x+y0+b,RGB(w,n,s));
pDC->SetPixel(-y+x0+f,x+y0+b,RGB(w,n,s));
pDC->SetPixel(-y+x0+f,-x+y0+b,RGB(w,n,s));
pDC->SetPixel(y+x0+f,-x+y0+b,RGB(w,n,s));
}
}
x=x+1;
if(d<0)
d=d+2*x+3;
else
d=d+2*(x-y)+5,y--;
}
}
<2>绘制多边形:
voidCyuan:
:
OnButton3()
{
CDC*pDC=GetDC();
{
CClientDCdc(this);
CPen*pOldpen;
CPenpen;
pen.CreatePen(PS_SOLID,m,RGB(w,n,s));
pOldpen=pDC->SelectObject(&pen);
SelectObject(*pDC,pen);
x[a]=x[0];
y[a]=y[0];
pDC->MoveTo(x[0],y[0]);
for(inti=0;i<=a-1;i++)
{
pDC->LineTo(x[i],y[i]);
}
DeleteObject(pen);
}
CDialog:
:
OnLButtonUp(nFlags,point);
}
<3>扫描线种子填充代码:
voidCyuan:
:
OnButton4()
{
{
CDC*pDC=GetDC();
intx0=xs;
inty0=ys;
longtop=0;
intflag,xn;
push(xs,ys,top);
while(top>0)
{
pop(xs,ys,top);
intx0=xs;
inty0=ys;
pDC->SetPixel(x0,y0,RGB(w,n,s));
while(pDC->GetPixel(x0+1,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0+1,y0)!
=RGB(w,n,s))
{
pDC->SetPixel(x0+1,y0,RGB(w,n,s));
x0++;
}
intxr=x0-1;
x0=xs,y0=ys;//记录右边界,准备向种子像素的左边填充
while(pDC->GetPixel(x0-1,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0-1,y0)!
=RGB(w,n,s))
{
pDC->SetPixel(x0-1,y0,RGB(w,n,s));
x0--;
}
intxl=x0+1;
x0=xl,y0=ys+1;
while(x0<=xr)
{
flag=0;
while(pDC->GetPixel(x0,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0,y0)!
=RGB(w,n,s)&&x0<=xr)
{
if(flag==0)
flag=1;
x0++;
}
if(flag==1)//相邻上一行有要填充的区域,新的种子像素坐标入栈
{
if(x0==xr&&pDC->GetPixel(x0,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0,y0)!
=RGB(w,n,s))
push(x0,y0,top);
else
push(x0-1,y0,top);
flag=0;
}
intxn=x0;
while(pDC->GetPixel(x0,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0,y0)!
=RGB(w,n,s)&&x0<=xr)
x0++;
if(xn==x0)
x0++;
}
x0=xl;y0=ys-1;//准备向相邻下一行寻找新的种子像素坐标入栈
while(x0<=xr)
{
flag=0;
while(pDC->GetPixel(x0,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0,y0)!
=RGB(w,n,s)&&x0<=xr)
{
if(flag==0)
flag=1;
x0++;
}
if(flag==1)
{
if(x0==xr&&pDC->GetPixel(x0,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0,y0)!
=RGB(w,n,s))
push(x0,y0,top);
else
push(x0-1,y0,top);
flag=0;
}
xn=x0;
while(pDC->GetPixel(x0,y0)!
=RGB(0,0,0)&&pDC->GetPixel(x0,y0)!
=RGB(w,n,s)&&x0<=xr)
x0++;
if(xn==x0)
x0++;
}
}
}
//********多边形扫描线填充**********//
voidCyuan:
:
OnButton5()
{
CDC*pDC=GetDC();
CClientDCdc(this);
CPen*pOldpen;
CPenpen;
pen.CreatePen(PS_SOLID,m,RGB(w,n,s));
pOldpen=pDC->SelectObject(&pen);
SelectObject(*pDC,pen);
intxd[100],yd[100];
intt,i,h,k;
intxmin,xmax;
xmin=x[0],xmax=x[0];
for(i=1;i{
if(x[i]xmin=x[i];
if(x[i]>xmax)
xmax=x[i];
}
for(h=xmin;h<=xmax;h++)
{
k=0;
for(i=0;i<=a-1;i++)//求交点
{
if(x[i+1]!
=x[i])
{
if((h+0.5-x[i])*(h+0.5-x[i+1])<0)
{
yd[k]=y[i]+(y[i+1]-y[i])*(h-x[i])/(x[i+1]-x[i]);
xd[i]=h;
k++;
}
}
}
//交点排序
for(i=0;i{
m=i;
for(intj=i+1;j<=k-1;j++)
if(yd[j]m=j;
if(m!
=j)
{
t=yd[i];
yd[i]=yd[m];
yd[m]=t;
}
}
for(i=0;i<=k-1;i=i+2)//交点填充
{
pDC->MoveTo(h,yd[i]);
pDC->LineTo(h,yd[i+1]);
}
}
DeleteObject(pen);
}
<4>清屏代码:
voidCyuan:
:
OnButton2()
{
Invalidate();
xs=0;
ys=0;
xe=0;
ye=0;
a=0;
for(inti=0;i{
x[i]=0;
y[i]=0;
}
}
实验结果:
画笔、RGB值均为零:
填充前:
填充后:
画笔宽度设置为2且RGB值不同:
填充前:
填充后:
遇到问题与解决方法:
问题1:
按下清屏按钮再重新画多边形的时候,清屏前多边形的原坐标仍然保存在数组里。
解决方法:
由于之前存放的顶点还在,必须把坐标顶点的值赋值为零即可。
问题2:
在进行圆的种子填充的时候,代码输入失误导致画完圆填充的时候只能填充半个圆。
解决办法:
在老师的帮助下终于找到了错误点,通过改正之后程序正确进行,颜色正确填充。
问题3:
在进行多边形填充进行画笔调用的时候,提示pDC、pen没有定义之类的错误,
解决办法:
通过观察,是由于CDC*pDC=GETDC()代码运行执行次序问题,而提示pen没有定义是因为粗心少写了一行代码。
总结与展望:
总结:
通过自己的努力,虽然还不是很完美,但是做出了开始预期的效果挺有成就感的,实现了动态画多边形,画圆并选择颜色进行填充的这些功能。
在画圆和多边形的时候实现了种子填充和扫描线调用画笔填充,通过自己动手明白了两者之间的相同和不同之处。
展望:
通过这次课程设计了解了很多关于图形学的知识。
同时对于编程中遇到的问题也熟悉了相关的解决办法,从中锻炼了自己的动手做实验的能力,但同时也让自己看清了自己的水平,在以后的生活里会多加强有关这方面的学习,从而提升自己在图形学方面的知识水平。