计算机图形学教程赵明,图形学基础(二)图形变换_上:2D 基本变换/复合变换...

本文介绍了如何使用C++和MFC进行2D图形的绘制,包括矩阵运算、坐标系建立以及平移、旋转、缩放和对称等基本变换。通过CDC类的成员函数实现图形绘制,利用矩阵变换实现几何图形的复合变换。同时提供了具体的代码示例,如矩阵计算、坐标系绘制和各种基本变换的实现方法。
摘要由CSDN通过智能技术生成

C++,MFC模板,VS2017

0800a6468082c0539b3aca0bb9483775.png

准备(2D图形、矩阵、坐标系)

typedef double array2d[5][5];

typedefdouble array[24];classCMyClass

{public:intxx, yy;//屏幕

array X, Y, Z, C;

array2d A1, A;//矩阵public:

CMyClass();virtual ~CMyClass();voidCalculate(array2d B);//矩阵计算voidDisplay();//显示void DrawView(CDC*pdc, CRect rr);//在坐标系内画图void moveto(double x, double y, CDC*pdc);void lineto(double x, double y, CDC*pdc);voidcleanB(array2d B);//矩阵复位

};

1、2D图形

(可使用CDC类的成员函数GetMapMode和SetMapMode来获得和设置当前映射模式:

int GetMapMode( ) const; // 返回当前的映射模式

virtual int SetMapMode( int nMapMode ); // 返回先前的映射模式)

在默认映射模式(MM_TEXT)下:

f9bb675aacce055acb637586753aa35e.png

代码(给到了初始化):

CMyClass::CMyClass()

{

X[1] = 20; Y[1] = -20; C[1] = 1;

X[2] = 20; Y[2] = -80; C[2] = 1;

X[3] = 40; Y[3] = -60; C[3] = 1;

X[4] = 60; Y[4] = -80; C[4] = 1;

X[5] = 60; Y[5] = -20; C[5] = 1;

X[6] = 25; Y[6] = -20; C[6] = 1;

X[7] = 25; Y[7] = -70; C[7] = 1;

X[8] = 40; Y[8] = -50; C[8] = 1;

X[9] = 55; Y[9] = -70; C[9] = 1;

X[10] = 55; Y[10] = -20; C[10] = 1;

}

2、矩阵

矩阵计算:

voidCMyClass::Calculate(array2d B)

{

for (int i = 1; i <= 10; ++i) {

X[i]= X[i] * B[1][1] + Y[i] * B[2][1] + C[i] * B[3][1];

Y[i]= X[i] * B[1][2] + Y[i] * B[2][2] + C[i] * B[3][2];

}

}

矩阵清零:

voidCMyClass::cleanB(array2d B)

{inti, j;for (i = 1; i <= 3; ++i) {for (j = 1; j <= 3; ++j) {

B[i][j]= 0;

}

}

}

3、坐标系

以屏幕中点为原点,x向右,y向上为正方向

void CGeoTrans2DView::OnDraw(CDC*pDC)

{

CGeoTrans2DDoc* pDoc =GetDocument();

ASSERT_VALID(pDoc);if (!pDoc)return;//TODO: 在此处为本机数据添加绘制代码//画坐标系

RECT rectWnd;

GetClientRect(&rectWnd);//获取窗口大小

pDC->MoveTo(rectWnd.right / 2 , rectWnd.bottom / 2 - 200);

pDC->LineTo(rectWnd.right / 2 , rectWnd.bottom / 2 + 200);

pDC->MoveTo(rectWnd.right / 2 - 200, rectWnd.bottom / 2);

pDC->LineTo(rectWnd.right / 2 + 200, rectWnd.bottom / 2);

ReleaseDC(pDC);//绘制字符图形CMyClass my1;//A1 矩阵清零

my1.cleanB(my1.A1);//A1 矩阵赋值

my1.A1[1][1] = 1;

my1.A1[2][2] = 1;

my1.A1[3][3] = 1;//A 矩阵清零

my1.cleanB(my1.A);

my1.Display();

}

基本变换(平移、旋转、缩放、对称)

(两种矩阵表示方式)以下采用第一种表示方式:

f24ef026f8a0732d5a5fae35d0f7a11e.png

1、平移

只改变矩阵 [3] [1],[3] [2] 位置的值即可:

82332a5a180e21eba6abfe1b31da4c0a.png

M平移了(x+15,y+45)

voidCGeoTrans2DView::OnTranslation()

{//TODO: 在此添加命令处理程序代码

CMyClass my;

my.cleanB(my.A1);

my.A1[1][1] = 1;

my.A1[2][2] = 1;

my.A1[3][3] = 1;

my.A1[3][1] = 15;

my.A1[3][2] = -45;

my.Display();

}

2、旋转

只改变矩阵 [1] [1],[1] [2],[2] [1],[2] [2] 位置的值:

93cb97bbe9a285faa3b8ec72cf7b477b.png

逆时针旋转30°

voidCGeoTrans2DView::OnRotation()

{//TODO: 在此添加命令处理程序代码

CMyClass my;

my.cleanB(my.A1);

my.A1[1][1] = cos(PI / 6);

my.A1[1][2] = -sin(PI / 6);

my.A1[2][1] = sin(PI / 6);

my.A1[2][2] = cos(PI / 6);

my.A1[3][3] = 1;

my.Display();

}

3、缩放

a357e1ce39aed635f7a57b3dfe5d9042.png

该代码没有对Z进行处理,所以此处用下面的一种方法(有误:应该是放大 1/x 倍),是不可行的

voidCGeoTrans2DView::OnScaling()

{//TODO: 在此添加命令处理程序代码

CMyClass my;

my.cleanB(my.A1);

my.A1[1][1] = 3;

my.A1[2][2] = 3;

my.A1[3][3] = 1;

my.Display();

}

4、对称

a69428c3bedf3a58c8123594588ada38.png

x轴对称

voidCGeoTrans2DView::OnMirrorX()

{//TODO: 在此添加命令处理程序代码

CMyClass my;

my.cleanB(my.A1);

my.A1[1][1] = 1;

my.A1[2][2] = -1;

my.A1[3][3] = 1;

my.Display();

}

复合变换(级联)

级联变换:一种以上的基本变换

1、非原点缩放

126c6dbfa06fa8eac28b6bfe4baed42c.png

以(-40,-40)为中心,放大3倍

voidCGeoTrans2DView::OnScalingxy()

{//TODO: 在此添加命令处理程序代码

CMyClass my;

my.cleanB(my.A1);

my.cleanB(my.A);//将(-40,-40)移到原点

my.A1[1][1] = 1;

my.A1[2][2] = 1;

my.A1[3][3] = 1;

my.A1[3][1] = 40;

my.A1[3][2] = -40;

my.Calculate(my.A1);//缩放3

my.A[1][1] = 3;

my.A[2][2] = 3;

my.A[3][3] = 1;

my.Calculate(my.A);//从原点复位

my.cleanB(my.A1);

my.A1[1][1] = 1;

my.A1[2][2] = 1;

my.A1[3][3] = 1;

my.A1[3][1] = -40;

my.A1[3][2] = 40;

my.Calculate(my.A1);

my.Display();

}

2、非原点旋转

a1c85916113ff2d4705d019f2e3c9d18.png

绕(0,40)旋转60°

voidCGeoTrans2DView::OnRotationxy()

{//TODO: 在此添加命令处理程序代码

CMyClass my;

my.cleanB(my.A1);

my.cleanB(my.A);//将(0,40)移到原点

my.A1[1][1] = 1;

my.A1[2][2] = 1;

my.A1[3][3] = 1;

my.A1[3][2] = 40;

my.Calculate(my.A1);//旋转60°

my.A[1][1] = cos(PI / 3);

my.A[1][2] = -sin(PI / 3);

my.A[2][1] = sin(PI / 3);

my.A[2][2] = cos(PI / 3);

my.A[3][3] = 1;

my.Calculate(my.A);//从原点复位

my.cleanB(my.A1);

my.A1[1][1] = 1;

my.A1[2][2] = 1;

my.A1[3][3] = 1;

my.A1[3][2] = -40;

my.Calculate(my.A1);

my.Display();

}

参考资料:

1、《计算机图形学原理及算法教程》和青芳 编著

2、计算机图形学 - 中国农业大学 赵明老师视频

本文采用CC BY 4.0知识共享许可协议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值