一、实验目的和要求
通过本次实验,掌握Behamsen或DDA方法绘制直线、圆或椭圆算法原理,加深对算法的理解,并采用Vc++提供的绘图函数实现多义线、矩形、多边形的绘制。了解区域填充的实现过程。
二、实验环境
1.硬件环境:PC机
2.软件环境: Windows 环境、Vc++编程
三、实验内容
1.实现Bresenham直线生成算法或DDA方法绘制直线、圆或椭圆算法
2.实现多义线、矩形、多边形的绘制
四、实验要求
(1)认真分析实验内容和要求,复习相关的理论知识,选择适当的解决方案;
(2)编写上机实验过程,作好上机前的准备工作;
(3)编写Bresenham直线生成算法或DDA绘制直线的函数
(4)编写Bresenham绘制园、椭圆函数
(5)了解并实现多义线、矩形、多边形的绘制方法。
(6)上机实践,记录实验结果(包括必要的中间结果);
(7)分析实验结果,并提供系统屏幕抓屏。
五、算法原理
1.DDA算法:直接利用计算x轴上的增量 x或y轴的增量 y的线段扫描转换算法。
若线段的斜率m的绝对值小于等于1,则在单位x间隔( x=1)取样,计算每个y的值,即 。
.若线段的斜率m的绝对值大于1,则在单位y间隔( y=1)取样,计算每个x的值,即
2.Bresenham直线生成算法:用线段上的点和上下相邻像素点间距离的对比来选择合适的像素点。
定义线段上的某一点到下像素点的距离为的d1,到上像素点的距离为d2,定义 d=d1-d2, ,并求出 的值。
根据相应的 的值来选取点。即 的值大于0,则取上像素点,且 ;若 的值小于0,则取下像素点,且 ;
3.Bresenham绘制园、椭圆:
算法内容:输入椭圆的长短轴来绘制
注释:这些代码的绘制全是基于MFC的onDrawview()里面进行的
如果老师要求要加上坐标轴代码如下
CRect rc;
GetClientRect(&rc);
pDC->SetMapMode(4);
pDC->SetViewportOrg(rc.right/2,rc.bottom/2);
pDC->MoveTo(-rc.right,0);
pDC->LineTo(rc.right,0);
pDC->MoveTo(0,rc.bottom);
pDC->LineTo(0,-rc.bottom);
pDC->TextOut(450,250,"第一象限");
pDC->TextOut(-450,250,"第二象限");
pDC->TextOut(-450,-250,"第三象限");
pDC->TextOut(450,-250,"第四象限");
pDC->TextOut(520,0,"X轴");
pDC->TextOut(0,260,"Y轴");
DDA(int x1, int y1, int x2, int y2, CDC *pDC)
{ int dx, dy ,epsl,k;
float x,y,xIncre,yIncre;
dx=x2-x1; dy=y2-y1;
x=x1; y=y1;
if (abs(dx)>abs(dy))
epsl=abs(dx);
else
epsl=abs(dy);
xIncre=(float)dx/(float)epsl
yIncre=(float)dy/(float)epsl;
CPoint P;
for(k=0;k<=epsl;k++)
{
P.x=int (x+0.5); P.y=int (y+0.5);
pDC->SetPixel(P.x,P.y,RGB(255,0,0));
x+=xIncre;
y+=yIncre;
}
}
DDA算法的调用:DDA(0,0,300,300,pDC);
DDA(0,0,-100,300,pDC);
DDA(0,0,-100,-300,pDC);
DDA(0,0,100,-300,pDC);
2.中点Bresenham算法绘制直线
中点Bresenham算法函数:
MidBresenham(int x1, int y1, int x2, int y2, CDC *pDC)
{
int dx,int dy,d ,UpIncre,DownIncre,x,y;
if (x1>x2){
x=x2;
x2=x1;
x1=x;
}
x=x1;
y=y1;
dx=x2-x1;
dy=y2-y1;
d=dx-2*dy;
UpIncre=2*dx-2*dy;
DownIncre=-2*dy;
while(x<=x2)
{
pDC->SetPixel(x,y,RGB(225,0,0));
x++;
if(d<0){
y++;
d+=UpIncre;
}
else
{
d+=DownIncre;
}
}
}
函数调用:
MidBresenham(0,0,300,300,pDC);
MidBresenham(-10,-10,-300,-300,pDC);
MidBresenham(0,0,-300,300,pDC);
MidBresenham(10,-10,300,-300,pDC);
3.Bresenham算法绘制直线
Bresenham算法函数:
Bresenham(int x0, int y0, int x1, int y1, CDC *pDC)
{
int x,y,dx,dy,e;
dx=x1-x0;
dy=y1-y0;
e=-dx;
x=x0;
y=y0;
while(x<=x1)
{
pDC->SetPixel(x,y,RGB(0,225,0));
x++;
e=e+2*dy;
if(e>0)
{
y++;
e=e-2*dx;
}
}
}
函数调用: Bresenham(-50,-100,200,300,pDC);
4.系统函数直接绘制直线`
②代码:for(int i=0;i<300;i++)
pDC->SetPixel(1*i,50,RGB(225,0,0));
for(int j=0;j<400;j++)
pDC->SetPixel(2*j,100,((COLORREF)0x0000FF00));
pDC->MoveTo(-100,40);
pDC->LineTo(-300,-400);
5.八分画画圆
CirclePoint(int x, int y, CDC *pDC)
{
pDC->SetPixel(x,y,RGB(255,0,0));
pDC->SetPixel(y,x,RGB(255,0,0));
pDC->SetPixel(-y,x,RGB(255,0,0));
pDC->SetPixel(-x,y,RGB(255,0,0));
pDC->SetPixel(-x,-y,RGB(255,0,0));
pDC->SetPixel(-y,-x,RGB(255,0,0));
pDC->SetPixel(y,-x,RGB(255,0,0));
pDC->SetPixel(x,-y,RGB(255,0,0));
}
函数调用:
CirclePoint(10, 50, pDC);
6.中点Bresenham绘制圆
中点Bresenham算法函数:
MidBresenhamCircle(int r, CDC *pDC)
{
int x,y,d;
x=0;
x=r;
d=1-r;
while(x<=y)
{
pDC->SetPixel(x,y,RGB(255,0,0));
pDC->SetPixel(y,x,RGB(255,0,0));
pDC->SetPixel(-y,x,RGB(255,0,0));
pDC->SetPixel(-x,y,RGB(255,0,0));
pDC->SetPixel(-x,-y,RGB(255,0,0));
pDC->SetPixel(-y,-x,RGB(255,0,0));
pDC->SetPixel(y,-x,RGB(255,0,0));
pDC->SetPixel(x,-y,RGB(255,0,0));
if(d<0)
d+=2*x+3;
else
d+=2*(x-y)+5;
y--;
}
x++;
}
函数调用:
MidBresenhamCircle(100, pDC);
7.系统函数调用直接绘制圆
② 代码:pDC->SetViewportOrg(rc.right*3/4,rc.bottom/4);
pDC->Ellipse(-100,-100,100,100);
8,.中点Bresenham算法绘制椭圆
中点Bresenham算法函数:
MidBresenhamEllipse(int a, int b, CDC *pDC)
{
int x,y;
float d1,d2;
x=0;
y=b;
d1=b*b+a*a*(-b+0.25);
pDC->SetPixel(x,y,RGB(255,10,255));
pDC->SetPixel(-x,-y,RGB(255,10,255));
pDC->SetPixel(-x,y,RGB(255,10,255));
pDC->SetPixel(x,-y,RGB(255,10,255));
while (b*b*(x+1)SetPixel(x,y,RGB(255,10,255));
pDC->SetPixel(-x,-y,RGB(255,10,255));
pDC->SetPixel(-x,y,RGB(255,10,255));
pDC->SetPixel(x,-y,RGB(255,10,255));
}
d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;
while(y>0)
{
if(d2<=0)
{
d2+=b*b*(2*x+2)+a*a*(-2*y+3);
x++;
y--;
}
else
{
d2+=a*a*(-2*y+3);
y--;
}
pDC->SetPixel(x,y,RGB(255,10,255));
pDC->SetPixel(-x,-y,RGB(255,10,255));
pDC->SetPixel(-x,y,RGB(255,10,255));
pDC->SetPixel(x,-y,RGB(255,10,255));
}
}
函数调用:MidBresenhamEllipse(200, 50, pDC);
9.系统直接调用绘制椭圆
pDC->SetViewportOrg(rc.right/4,rc.bottom/4);
pDC->Ellipse(-200,-50,200,50);
10.多义曲线的绘制
pDC->SetViewportOrg(rc.right*3/4,rc.bottom*3/4);
CPoint pt[7];
pt[0].x=-150;pt[0].y=0;
pt[1].x=-100;pt[1].y=-75;
pt[2].x=-50; pt[2].y=-75;
pt[3].x=0; pt[3].y=0;
pt[4].x=50;pt[4].y=75;
pt[5].x=100; pt[5].y=75;
pt[6].x=150; pt[6].y=0;//使用现成的CDC类成员函数,绘制Bezier曲线;
pDC->PolyBezier(pt,7);
11.矩形的绘制
pDC->Rectangle(10,20,300,200);//绘制矩形
pDC->Rectangle(10,10,200,200);//绘制正方形
12.多边形的绘制
pDC->SetViewportOrg(rc.right*3/4,rc.bottom*3/4);
CPoint pt[7];
pt[0].x=-150;pt[0].y=0;
pt[1].x=-100;pt[1].y=-75;
pt[2].x=-50; pt[2].y=-75;
pt[3].x=0; pt[3].y=0;
pt[4].x=50;pt[4].y=75;
pt[5].x=100; pt[5].y=75;
pt[6].x=150; pt[6].y=0;//使用现成的CDC类成员函数,绘制Bezier曲线;
pDC->Polygon(pt,7);//绘制多边型
13.扇形的绘制
② 代码: pDC->Pie(-100,-100,100,100,-100,-100,100,150);
14.圆弧的绘制
pDC->SetViewportOrg(rc.right/4,rc.bottom*3/4);
pDC->Arc(-100,-100,100,100,-100,0,100,0);