计算机图形学实验:二维图形变换
实验三二维图形变换
一、实验任务
1. 通过二维几何变换的数学模型,编写缩放、旋转、对称变换; 2. 实现图形变换的交互式操作:缩放、旋转、对称变换等;
二、实验内容
1. 放大缩小变换
放大缩小变换公式为:x ’=x..Sx , y ’=y.Sy ; 其中S x ,S y 分别为x,y 方向的放缩比例系数。
变换矩阵表达式为: [x’ y ’
(1)S x =Sy =1.5;等比例放大 (2)S x =Sy =0.5;等比例缩小 2. 对称变换
包括以x 轴对称、y 轴对称和原点O 对称三种。由于屏幕坐标只有第一象限,我们可以将原点平移到(500,240)处。在第一象限画出一个三角形,然后分别求出三个对称图形。 3. 旋转变换
将图形上的点(x ,y )旋转θ角度,得到新的坐标(x’,y ’
) 为: x ’=xcosθ-ysin θ, y ’=xsinθ+ycosθ;
[x’ y ’ 4.
三、设计思路
1. 通过二维几何变换的数学模型,编写缩放、旋转、对称变换;
2. 以(500,240)为原点建立图形变换的参考坐标系; 3. 通过键盘按键控制图形的缩放、旋转、对称变换;
4. 变换图形设定为以Pt[0](540,220) 、Pt[1](670,130) 、Pt[2](560,120) 为顶点的
三角形。
步骤:
1. 2.
建立Trans 工程文件;
利用Resource View设计菜单,如图所示;
3.
在CTransView 视图类中添加消息映射函数;
4. 添加自定义的成员变量:
CPoint Pt[3];//三角形定点数组 float dAngle;//每一次旋转的角度
在视图类CPP 文件的构造函数中初始化成员变量
Pt[0].x = 540; Pt[0].y = 220; Pt[1].x = 670; Pt[1].y = 130; Pt[2].x = 560; Pt[2].y = 120; dAngle = 0;
5. 在视图类的OnDraw()函数中加入下列代码,实现视图绘图。
void CTransView::OnDraw(CDC* pDC) {
CTransDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//绘出以以(540,220) 、(670,130) 、(560,120) 为顶点的三角形。 pDC->MoveTo(Pt[0]); pDC->LineTo(Pt[1]); pDC->LineTo(Pt[2]); pDC->LineTo(Pt[0]);
//绘出以(500,240)为原点的坐标轴
pDC->MoveTo(100,240);pDC->LineTo(900,240); pDC->MoveTo(500,5);pDC->LineTo(500,400);
pDC->TextOut(900,235,"x轴"); pDC->TextOut(500,400,"y轴"); //控制信息
pDC->TextOut(15,10,"对称变换:键盘方向键");
pDC->TextOut(15,28,"缩放变换:Z 键缩小;X 键放大"); pDC->TextOut(15,46,"旋转变换:键盘R 键"); }
6. 添加预编译常量
#define PI 3.1415926
7. 分别编写步骤3中向视图类中添加消息映射函数,程序如下:
void CTransView::OnTransformRotate() {
// TODO: Add your command handler code here float dRadiusAngle = 30.0 * PI /180.0; for(int i=0; i
RedrawWindow(); }//实现图形旋转
void CTransView::OnTransformScale() {
// TODO: Add your command handler code here float dScaleX = 2.0; float dScaleY = 0.5; for(int i=0; i
RedrawWindow(); }//实现图形缩放
void CTransView::OnTransformSymmetry() {
// TODO: Add your command handler code here
for(int i=0; i
RedrawWindow(); }//实现图形对称
8. 添加成员函数实现键盘交互式控制图形变换
函数及代码如下:
void CTransView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
// TODO: Add your message handler code here and/or call default
int i=0;
CPoint TmpPt = Pt[0]; switch (nChar){ case VK_UP: //上 for(i=0; i
case VK_LEFT: //左 for(i=0; i
case VK_RIGHT: //右 for(i=0; i
} break;
case 0X5A: //Z的ASCII 码 Pt[1] = Pt[1] - Pt[0]; Pt[2] = Pt[2] - Pt[0]; Pt[0].x = Pt[0].y = 0; for(i=1; i
case 0X58: //X的ASCII 码 Pt[1] = Pt[1] - Pt[0]; Pt[2] = Pt[2] - Pt[0]; Pt[0].x = Pt[0].y = 0; for(i=1; i
case 0X52 : //R的ASCII 码 dAngle = -1.0;//每一次逆时针旋转一度 float dRadiusAngle = dAngle * PI /180.0; Pt[1] = Pt[1] - Pt[0]; Pt[2] = Pt[2] - Pt[0]; Pt[0].x = Pt[0].y = 0;
for(int i=1; i
所以如果计算出是负值来时,就直接赋0
{ Pt[i].x = (float)Pt[i].x * cos(dRadiusAngle) - (float)Pt[i].y * sin(dRadiusAngle);
Pt[i].y = (float)Pt[i].x * sin(dRadiusAngle) + (float)Pt[i].y * cos(dRadiusAngle);
} Pt[0] = TmpPt;
Pt[1] = Pt[1] + Pt[0]; Pt[2] = Pt[2] + Pt[0]; break; }
RedrawWindow();
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
9. 编译和运行程序,查看程序运行结果
四、实验效果及分析
运行程序:
按方向键“←”:
按方向键“↓”
按“X ”键
进行旋转变换时,发现三角形的形状会有略微变化。