资源描述
几何图形变换和函数曲线的画法
一、实验目的和要求
1、巩固所学理论知识,加深对二维变换的理解,加深理解利用变换矩阵可由简单图形得到复杂图形,加深对变换矩阵算法的理解。
2、熟悉vc++6.0下实践图形算法(要求编制绘制“M” 以及正叶线和蝴蝶结的程序。编程实现变换矩阵算法,绘制给出变换后的视图,调试程序及分析运行结果。)
二、实验步骤
1、实验内容(含实验原理介绍):
(1)二维几何变换:
原理:图形变换的主要功能是把用户坐标系和图形输出设备的坐标系联系起来;图形基本变换是指图形的比例变换、对称变换、错切变换、平移变换等。通过对原图上二维向量引进第三个坐标,即三维点向量(又称其次坐标点),简称其次坐标,这样在三维坐标下,二维几何变换都可统一用一个矩阵表示。所谓其次坐标就是将一个原本是n维的向量用一个n+1维向量来表示。引进其次坐标的的优点:①、提供了矩阵运算把二维、三维甚至高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法;②、可以表示无穷远点。
步骤:①创建工程名为“二维图形变换”的单文档应用程序的框架。并编辑菜单资源(如下图)
相对于原点的变比
平移
旋转
复合变换
变比
基本图形变换
基本图形变换
基本图形变换
基本图形变换
绕非原点旋转
关于X轴对称
基本图形变换
关于Y轴对称
对称
基本图形变换
基本图形变换
基本图形变换
基本图形变换
基本图形变换
基本图形变换
基本图形变换
关于原点轴对称
基本图形变换
基本图形变换
②添加消息处理函数。利用Class Wizard(建立类向导)为应用程序添加与菜单项的消息处理函数,ClassName栏中选择CMyView,建立消息映射函数,完成函数声明。
③手工添加几何变换绘图基类。为程序模块化,对绘制几何图形变换编制了基类MyClass类。在工程中选择“文件” “新建”命令,在弹出的新建对话框中,选择C/C++ Header File ,在“文件”名称输入栏中输入MyClass;同样,在工程中选择“文件” “新建”命令,在弹出的新建对话框中,选择C/C++ Source File ,在“文件”名称输入栏中输入MyClass。在工作区中系统自动创建的相应的空文件中,分别添加此基类的头文件(.h文件)和应用文件(.cpp文件)。
(2)正叶线和蝴蝶结:
正叶线是一种类似植物叶子形状的曲线,数学表达式:r=a*sin(n*θ)
x=r*cosθ
y=r*sinθ
其中(a>0,n=2,3,4,5……)
蝴蝶结,顾名思义即类似于蝴蝶结的图案。是经过设置二维坐标x,y函数以及利用旋转变换绘制的图案。画线点的x坐标、y坐标以下列函数规律变化
d=80;
for(a=0;a<=2*pi;a+=pi/360){
e=d*(1+0.25*sin(4*a));
e=e*(1+sin(8*a));
x2=int(320+e*cos(a+pi/8));
x1=int(320+e*cos(a));
y1=int(200+e*sin(a));
y2=int(200+e*sin(a+pi/8));
}
正叶线
步骤:①、创建工程名为“函数曲线”的单文档应用程序的框架。并定义编辑菜单资源(如下图)
函数曲线
蝴蝶结
②添加消息处理函数。利用Class Wizard(建立类向导)为应用程序添加与菜单项的消息处理函数,ClassName栏中选择CMyView,建立消息映射函数,完成函数声明。
③在**View.h、**View.cpp添加完成各个菜单消息处理函数,实现既定功能。
基本图形变换
2、核心程序(源代码)
(1)平移
void CMyView::OnTranslation()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=1;
my1.A[2][2]=1;
my1.A[3][1]=15;
my1.A[3][2]=45;
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(2)旋转
void CMyView::OnRotation()
{
int i,j;
CMyClass my1;
for(i=1; i<=3; ++i)
{
for(j=1; j<=3; ++j)
my1.A[i][j]=0;
}
my1.A[1][1]=cos(PI/6);
my1.A[1][2]=sin(PI/6);
my1.A[2][1]=-cos(PI/6);
my1.A[2][2]=sin(PI/6);
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(3)对比
void CMyView::OnScaling()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=5;
my1.A[2][2]=2;
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(4)关于x轴对称
void CMyView::OnMirrorX()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=1;
my1.A[2][2]=-1;
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(5)关于y轴对称
void CMyView::OnMirrorY()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=-1;
my1.A[2][2]=1;
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(6)关于原点对称
void CMyView::OnMirrorO()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=-1;
my1.A[2][2]=-1;
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(7)相对非原点的变化比
void CMyView::OnScalingxy()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=1;
my1.A[2][2]=1;
my1.A[3][3]=1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=2;
my1.A[2][2]=2;
my1.A[3][2]=-10;
my1.A[3][1]=-5;
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(8)绕非原点旋转
void CMyView::OnRotationxy()
{
int i,j;
CMyClass my1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A1[i][j]=0;
}
my1.A1[1][1]=1;
my1.A1[2][2]=1;
my1.A1[3][3]=1;
for(i=1;i<=3;++i)
{
for(j=1;j<=3;++j)
my1.A[i][j]=0;
}
my1.A[1][1]=cos(PI*60);
my1.A[1][2]=sin(PI*60);
my1.A[2][1]=-sin(PI*60);
my1.A[2][2]=cos(PI*60);
my1.A[3][1]=(1-cos(PI*60))*10-5*sin(PI*60);
my1.A[3][2]=(1-cos(PI*60))*5+10*sin(PI*60);
my1.A[3][3]=1;
RedrawWindow();
my1.Display();
}
(9)正叶线
void CMyView::OnDrawLeaf()
{
CClientDC*pdc=new CClientDC(this);
CPen pen;
pen.CreatePen(PS_SOLID,1,RGB(0,0XFF,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
int a,n,cx,cy,gx,gy,flag,k;
double r,p,th,x,y,pi;
a=160; n=2; pi=3.14159;
cx=320;
cy=240;
flag=0; k=200;
RedrawWindow();
for(p=1;p>=0.2;p-=0.2)
{
for(th=0;th<=2*pi+0.1;th+=pi/k)
{
r=abs(a*cos(n*th)*p);
x=int(r*cos(th));
y=int(r*sin(th));
gx=int(cx+x);
gy=int(cy+y);
if(flag==0)
{
pdc->MoveTo(gx,gy);
}//,RGB(255,0,0));}
flag=1;
pdc->LineTo(gx,gy);
}
flag=0;
}
pdc->DeleteDC();
}
(10)蝴蝶结
void CMyView::OnDrawRose()
{
RedrawWindow();
int d,k,x1,x2,y1,y2;
float pi,a,e;
CClientDC *pdc=new CClientDC(this);
CPen pen;
pen.CreatePen(PS_SOLID,1,RGB(0xff,0,0));
CPen *oldpen=(CPen*)pdc->SelectObject(&pen);
pi=3.14159;
d=80;
for(a=0;a<=2*pi;a+=pi/360) {
e=d*(1+0.25*sin(4*a));
e=e*(1+sin(8*a));
x1=int(320+e*cos(a));
x2=int(320+e*cos(a+pi/8));
y1=int(200+e*sin(a));
y2=int(200+e*sin(a+pi/8));
pdc->MoveTo(x1,y1);
pdc->LineTo(x2,y2);
}
delete pdc;
}
三、实验结果
备注:截图添加到WORD中可能与原始长宽比例有不一致
(1)初始界面
(2)各种变换过程截图
图1、平移 图2、旋转
图3、变比
图4、关于x轴对称 图5、关于y轴对称
图6、原点轴对称 图7、相对非原点的变化比
图8、正叶线
图9、蝴蝶结
(3)总结
该程序能够顺利地实现二维图形的绘制以及一般变换,能够轻松画出函数曲线正叶线和蝴蝶结。
四、参考文献
1、和青芳,计算机图形学原理及算法教程,北京:清华大学出版社,2010
展开阅读全文