资源描述
计算机图形学实验报告
实验内容 直线中点Bresenham算法的实现
专 业 计算机科学与技术
班 级
学 号
姓 名
指导教师 刘长松
年月 日
一、实验题目
直线中点Bresenham算法的实现
二、实验要求
学习Visual C++ 6.0集成编程环境的使用、图形设备接口和常用图形程序设计、鼠标编程以及菜单设计等基础知识,从而掌握利用Visual C++进行图形程序设计的方法以及简单的图形画法,并编程实现Bresenham直线扫描转换程序,得出相应的输出图形。
三、实验内容
1. 学习Visual C++ 6.0集成编成环境的使用;
2. 掌握Visual C++ 6.0图形设备接口和常用图形程序设计、菜单设计等方法;
3. 编程实现Bresenham直线扫描转换程序,得出相应的输出图形;
四、实验过程
1、实验原理
Bresenham 算法 思想:
0≤d≤1
当d<0.5:下一个象素应取右光栅点(xi+1,yi)
当d≥0.5:下一个象素应取右上光栅点(xi+1,yi+1)
e=d-0.5 假定直线斜率|k|≤1。e0= -0.5,x每次加1,e = e + k; e<0时,下一像素取 (xi+1,yi),e = e + k ; e>0时,下一像素取 (xi+1,yi+1);e = e + k -1 ; e=0时,可任取上、下光栅点显示。
当斜率|k|>1时,同理,只是y每次加1,x是否变化取决于增量e。
中点算法
d =2F(M)=2F(Xp+1,Yp+0.5)=2(a(Xp+1)+b(Yp+0.5)+c) 其中a=y0-y1, b=x1-x0, c=x0y1-x1y0
当d<0,M在L(Q点)下方,取右上方T为下一个象素;
此时再下一个象素的判别式为:
d’ = 2F(Xp+2,Yp+0.5)=2(a(Xp+2)+b(Yp+0.5)+c) = 2(a(Xp+1)+b(Yp+0.5)+c) +2a = d + 2a; 当d>0,M在L(Q点)上方,取右方B为下一个象素;
此时下一个象素的判别式为:
d’ = 2F(Xp+2,Yp+1.5)=2(a(Xp+2)+b(Yp+1.5)+c)
= 2(a(Xp+1)+b(Yp+0.5)+c) +2(a +b) = d + 2(a + b); 当d=0,选T或B均可,约定取B为下一个象素; d0 = 2F(X0+1,Y0+0.5) = 2(a(X0+1)+b(Y0+0.5)+c) = 2(F(X0,Y0)+a+0.5b)
2、案例分析
MFC提供的CDC类的成员函数MoveTo()和LineTo()函数用于绘制傻
任意斜率的直线段,直线段的颜色由所选用的画笔指定。MoveTo()函数移动当前点到参数(x,y)所指定的点,不画线;LineTo()函数从当前点画一直线段到参数(x,y)所指定的点,但不包括(x,y)。 本案例通过定义Cline类来模拟CDC类绘制任意斜的直线段,采用直线中点Bresenham算法。
3、算法设计
对于0≤𝑘≤1的直线段,中点Bresenham算法如下:
(1)使用鼠标选择起点坐标p0(x0,y0)和终点坐标p1(x1,y1)。要求起点的的坐标小于等于终点的x坐标。
(2)定义直线段当前点坐标x,y,定义中点误差项d,定义直线斜k,定义像素点颜色clr。
(3)x=x0,y=y0,计算d=0.5-k,k=(y1-y0)/(x1-x0), clr=CRGB(0,0,1)
(4)绘制点(x,y),判断d的符号。若d<0,则(x,y)更新为(x+1,y+1),d更新为d+1-k;否则(x,y)更新为(x+1,y),d更新为d-k。
(5)如果当前点x<x1,重复步骤(4),否则结束。
4、主要代码
// Line.cpp: implementation of the CLine class.
#include "stdafx.h"
#include "Line.h"
#include "math.h"
#define Round(d) int(floor(d+0.5))//四舍五入宏定义
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CLine::CLine()
{
}
CLine::~CLine()
{
}
void CLine::MoveTo(CDC *pDC,CP2 p0)//绘制直线起点函数
{
P0=p0;
}
void CLine::MoveTo(CDC *pDC,double x0,double y0)//重载函数
{
P0=CP2(x0,y0);
}
void CLine::LineTo(CDC *pDC,CP2 p1)
{
P1=p1;
CP2 p,t;
CRGB clr=CRGB(0.0,0.0,0.0);//黑色像素点
if(fabs(P0.x-P1.x)<1e-6)//绘制垂线
{
if(P0.y>P1.y)//交换顶点,使得起始点低于终点
{
t=P0;P0=P1;P1=t;
}
for(p=P0;p.y<P1.y;p.y++)
{
pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255));
}
}
else
{
double k,d;
k=(P1.y-P0.y)/(P1.x-P0.x);
if(k>1.0)//绘制k>1
{
if(P0.y>P1.y)
{
t=P0;P0=P1;P1=t;
}
d=1-0.5*k;
for(p=P0;p.y<P1.y;p.y++)
{
pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255));
if(d>=0)
{
p.x++;
d+=1-k;
}
else
d+=1;
}
}
if(0.0<=k && k<=1.0)//绘制0<=k<=1
{
if(P0.x>P1.x)
{
t=P0;P0=P1;P1=t;
}
d=0.5-k;
for(p=P0;p.x<P1.x;p.x++)
{
pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255));
if(d<0)
{
p.y++;
d+=1-k;
}
else
d-=k;
}
}
if(k>=-1.0 && k<0.0)//绘制-1<=k<0
{
if(P0.x>P1.x)
{
t=P0;P0=P1;P1=t;
}
d=-0.5-k;
for(p=P0;p.x<P1.x;p.x++)
{
pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255));
if(d>0)
{
p.y--;
d-=1+k;
}
else
d-=k;
}
}
if(k<-1.0)//绘制k<-1
{
if(P0.y<P1.y)
{
t=P0;P0=P1;P1=t;
}
d=-1-0.5*k;
for(p=P0;p.y>P1.y;p.y--)
{
pDC->SetPixelV(Round(p.x),Round(p.y),RGB(clr.red*255,clr.green*255,clr.blue*255));
if(d<0)
{
p.x++;
d-=1+k;
}
else
d-=1; }}}
P0=p1;
}
void CLine::LineTo(CDC *pDC,double x1,double y1)//重载函数
{
LineTo(pDC,CP2(x1,y1));
}
四、 实验结果
程序运行时如所示图5-1结果
图5-1
点击绘图按钮是会出现如图5-2所示结果
图5-2
按左键绘图结果如图5-3
图5-3
五、 实验收获
计算机图形学是一种使用数学算法将二维或三维图形转化为计算机显示器的栅格形式的科学,研究的是应用计算机产生图像的所有工作,不管图像是静态的还是动态的,可交互的还是固定的
通过本次试验的设计,让我对计算机图形图像处理有了更加深刻的理解,学会了这种绘制直线的算法Bresenham。Brensenham算法也是较为常用的算法。
10
展开阅读全文