计算机图形学
实验报告
班级:0811102
学院:理学院
姓名:裴可锋
指导老师:戴群
一. 程序的实现环境
1.硬件配置
最低配置:CPU:Pentium3 800以上或其它兼容规格,内存:256M以上,硬盘:20GB以上空间
推荐配置:CPU:Pentium4 1.6G,内存:512M以上,硬盘:100GB以上空间。
2.操作系统
Windows97以上系统
3.编程语言
Matlab
二. 算法思想
(1)中点Bresenham算法
每次在最大位移方向上走一步,而另一个方向是走不还是不走步取决于误差的判别
(2)中点Bresenham画圆算法
对于该圆弧,由于最大位移方向是x,因此基本原理为:每次沿x方向走上一步,而y方向上减一或减零
(3)直线段裁剪Cohen-Sutherland裁剪算法
对p1(x1,y1)p2(x2,y2)分三种情况处理
1. 若p1和p2完全在裁剪窗口内,“简取之”
2. 若都在窗口外,且在同一侧,完全不可见“简弃之”
3. 若都不满足,则对进行分段,重复上述操作
(4)bazier曲线
利用递归公式将P(t)=分解为三个坐标分量的形式
三.使用方法
(1)中点Bresenham算法
向主函数输入线段的两个端点坐标以及斜率,与y轴交点坐标
(2)中点Bresenham画圆算法
输入半径即可
(3)直线段裁剪Cohen-Sutherland裁剪算法
输入两个端点的坐标
(4)bazier曲线
输入四个点的坐标
四.实验结果图示
(1)中点Bresenham算法
(2)中点Bresenham画圆算法
(3)直线段裁剪Cohen-Sutherland裁剪算法
(4)bazier曲线
五.实验程序及适用范围
(1) 中点Bresenham算法
function fun(x0,y0,x1,y1,k,t)
if x0>x1
x=x0;x1=x0;x0=x;
y=y0;y1=y0;y0=y;
end
x=x0;
y=y0;
dx=x1-x0;
dy=y1-y0;
d=dx-2*dy;
up=2*dx-2*dy;down=-2*dy;
while x<x1||x==x1
plot(x,y,'*');
hold on;
x=x+1;
if d<0
y=y+1;
d=d+up;
else
d=d+down;
end
end
a=x0:1:x1;
b=k*a+t;
hold on;
plot(a,b)
grid on
set(gca,'ytick',[y0:1:y1])
(2) 中点Bresenham画圆算法
function fun1(r)
d=1-r;
x=0;
y=r;
while x<y
plot(x,y,'*');
hold on;
if d<0
d=d+2*x+3;
x=x+1;
y=y;
else
d=d+2*(x-y)+5;
x=x+1;
y=y-1;
end
end
(3) 线段的裁剪问题
主程序
function f3(x1,y1,x2,y2,yt,yb,xl,xr)
code1=f31(x1,y1,yt,yb,xl,xr);
code2=f31(x2,y2,yt,yb,xl,xr);
c=[0 0 0 0 ];
t=[0 0 0 0];
t=0;k=0;x=0;y=0;
if code1==c&code2==c
fun32(x1,y1,x2,y2);
else
for i=0:1:3
if code1(i)==code2(i)
disp('¸ÃÖ±Ïß²»ÔÚ´°¿ÚÄÚ');
t=1;
end
end
if t==0
while code1~=c or code2~=c
if code1==c
code1=code2;
c=code1;
code2=c;
x1=x2;
x=x1;
x2=x;
y1=y2;
y=y1;
y2=y;
end
k=(y2-y1)/(x2-x1);
switch code1
case code1==[0 1 0 1]
k1=(y2-yt)/(x2-xl);
if k1<k
x1=xl;
y1=(y2-y1)/(x2-x1)*(xl-x1)+y1;
else
x1=xl-(y2-yt)/(y2-y1)*(x2-x1);
y1=yt;
end
code1==[0 0 0 0];
case code1==[1 0 0 1]
k2=(y2-yb)/(x2-xl);
if k2<k
x1=xl;
y1=(y1-y2)/(x2-x1)*(x2-x1)+y2;
else
x1=x1+(x2-x1)/(y1-y2)*(y1-yb);
y1=yb;
end
code1==[0 0 0 0];
case code1==[1 0 1 0]
k3=(y2-yb)/(x2-xr);
if k3<k
x1=x1-(y1-yb)/(y1-y2)*(x1-x2);
y1=yb;
else
x1=xr;
y1=y1-(y1-y2)/(x1-x2)*(x1-xr);
end
code1==[0 0 0 0];
case code1==[0 1 1 0]
k4=(y2-yt)/(x2-xr);
if k4<k
x1=xr;
y1=(y2-y1)/(x1xx2)*(x1-xr)+y1;
else
x1=(y2-yt)/(x1-x2)*(x1-x2)+x2;
y1=yt;
end
code1==[0 0 0 0];
case code1==[0 1 0 0]
x1=x2-(y2-yt)/(y1-y2)*(x2-x1);
y1=yt;
code1==[0 0 0 0];
case code1==[0 0 0 1]
x1=xl;
y1=y2-(y2-y1)/(x2-x1)*(x2-xl);
code1==[0 0 0 0];
case code1==[1 0 0 0]
x1=x2+(x2-x1)/(y2-y1)*(y2-yb);
y1=yb;
code1==[0 0 0 0];
case code1==[0 0 1 0]
x1=xr;
y1=y2-(y2-y1)/(x2-x1)*(x2-xr);
code1==[0 0 0 0];
end
end
end
end
子程序
function f31(x,y,yt,yb,xl,xr)
c=[0 0 0 0];
if x<xl
c(0)=1;
else c(0)=0;
end
if x>xr
c(1)=1;
else c(1)=0;
end
if y<yb
c(2)=1;
else c(2)=0;
end
if y>yt
c(3)=1;
else c(3)=0;
end
function f32(x1,y1,x2,y2)
t=x1:0.01:x2;
y=y1:0.01:y2;
plot(t,y,'-');
(4) bazier曲线
function [Q]=bezierInterp(P0,P1,P2,P3,varargin)
if (nargin<4)
disp('Atleast four input arguments (four control points) are required');
return
end
[r0 c0]=size(P0); [r1 c1]=size(P1); [r2 c2]=size(P2); [r3 c3]=size(P3);
if (r0~=r1 || r0~=r2 || r0~=r3 || c0~=c1 || c0~=c2 || c0~=c3)
disp('arg1,arg2,arg3,arg4 must be of equal size');
return
end
t=linspace(0,1,101);
defaultValues = {t};
nonemptyIdx = ~cellfun('isempty',varargin);
defaultValues(nonemptyIdx) = varargin(nonemptyIdx);
[t] = deal(defaultValues{:});
[r c]=size(t);
if(r>1 && c>1)
disp('arg5 must be a vector');
return
end
c3 = -P0 + 3*(P1-P2) + P3;
c2 = 3*(P0 - (2*P1)+P2);
c1 = 3*(P1 - P0);
c0 = P0;
for k=1:length(t)
Q(k,:)=((c3*t(k)+c2)*t(k)+c1)*t(k) + c0;
end
function bezier(n)
close all;
nplot = 100;
figure(1);
hold on; box on;
set(gca,'Fontsize',16);
title('Choose 1 st control points');
t = linspace(0,1,nplot);
for i = 1:100
title(['Choose ',num2str(i),' th. control point']);
p(i,:) = ginput(1);
hold off;
plot(p(:,1),p(:,2),'k-','LineWidth',2);
axis([0 1 0 1]);
hold on; box on;
[X,Y,p_bez] = CASTELJAU(0,1,p,t);
plot(p_bez(:,1),p_bez(:,2),'b-','LineWidth',4);
plot(p(:,1),p(:,2),'ro','MarkerSize',10,'MarkerFaceColor','r');
end
title(['Bezier-curve with ',num2str(n),' control points']);
function B_para=B_para(i,n,t)
B_para=(1-t)^(n-i)*t^i;
function C=C(i,n)
C=factorial(n)/(factorial(i)*factorial(n-i));
六.测试用例
(1)中点Bresenham算法
P1=(0,0) p2=(5,8) k=5/8 t=0
Fun(0,0,5,8,5/8,0)
(2)中点Breseham算法
R=12
Fun1(12)
(3)
(4)bazier曲线
BazierIntep([0,3],[5,20],[7,2],[9,1)
第二篇:计算机图形学实验报告二
郑州轻工业学院
计算机图形学实验报告二
实验名称: 基本图形(圆)生成技术
班级: 计科07-2班
学号:
姓名:
日期: 20##-11-1
一、 实验目的:
在一个图形系统中,基本图形(也称为图元、图素等)的生成技术是最基本的,任何复杂的图形都是由基本图形组成的,基本图形生成的质量直接影响该图形系统绘图的质量。所以,需要设计出精确的基本图形生成算法,以确保图形系统绘图的精确性。本次实验的目的就是验证直线生成的三种扫描算法,并要求对基本算法进行扩充和改进,包括:利用Visual C++实现三种直线生成算法,验证算法的正确性;
二、 实验任务:
1. 理解三种直线生成算法思想,写出实现程序; 、
2. 添加鼠标功能,实现交互式画直线程序;
3. 将10个像素作为步距单位,编出Bresenham算法的示例。
三、实验内容:
任务一:实现DDA画线程序
实验步骤:
1. 建立一个DDALine的工程文件;
2. 添加ddaline()成员函数
方法:在工作区中选择CLASSVIEW类窗口,右击CDDAlineView类,选择“add member function…”,定义如下的成员函数:
void ddaline(CDC* pDC,int x0,int y0,int x1,int y1,COLORREF color);
3. 编译、调试和运行程序,查看程序结果。
任务二:放大10倍后,算法演示程序
先画出(100,100)到(600,400)大小为10的网格,然后从(100,100)以10为单位,计算出直线上各个像素位置。
步骤:
1. 建立DDA2Line工程;
2. 在OnDraw()函数中画出网格,并调用DDA2Line()函数
3.添加DDA2Line()成员函数
方法:在工作区中选择CLASSVIEW类窗口,右击CDDAlineView类,选择“add member function…”,定义如下的成员函数:
void DDA2Line(CDC* pDC,int x0,int y0,int x1,int y1,COLORREF color);
4.编写DDA2Line()函数
5.调试、运行程序。
任务三:加入鼠标功能,实现交互式画直线
第一步:建立DDAMouseLine工程文件;
第二步:向视图类中添加自定义的成员变量
用鼠标右键单击视图类,选择“Add Member Variable…”,添加下面三个成员变量。
第四步:在视图类CPP文件的构造函数中初始化成员变量。
视图类的构造函数名与该视图类的名字相同。在视图类中选择构造函数。
第五步:在视图类的OnDraw()函数中加入下列代码,实现视图绘图。
第六步:向视图类中添加鼠标OnLButtonDown()函数消息响应函数,并输入鼠标处理程序代码。
第七步:添加成员函数的程序代码。
四、实验结果和分析:
1. 查看实验结果,验证算法的正确性;
2. 对程序进行分析和比较,你还能提出哪些改进和扩充?例如:
(1)线刷子绘制直线和圆;
(2)方形刷子绘制直线和圆;
(3)虚线和点划线的绘制;
五、实验感受:
通过这次实验我学到了很多的东西,基本掌握了基本图形的的绘制方法。期间也遇到了或多或少的问题,可是经过老师的指导和自己的细心排查问题,终于还是都解决了。经过这次实验我觉得自己很受益匪浅,不仅加深了课程记忆,更让我对计算机图形学这门课程充满兴趣,我相信,只要自己足够用心,我是肯定会越学越好的。