今天yogurt和你們分享的是計算機圖形學裏算是最基礎的一個內容——二維空間裏的簡單矩形變換,變換方式包括平移、按比例縮放、旋轉、對稱和錯切。下一章yogurt分享了《三維空間裏的簡單的長方體透視變換》http://www.cnblogs.com/to-sunshine/p/6501208.html,想要進一步學習圖形的各類變換的同窗能夠去簡單學習一下。那麼,按照慣例yogurt又要給你們普及知識點啦~~html
---------------------------------------------------------yogurt小課堂開課啦--------------------------------------------------ide
在線性代數裏咱們學過矩陣的基本運算,它在空間圖形的變換中起着尤其關鍵的做用。咱們把二維空間的每個點的座標記爲(x,y,1),三維空間的每個點的座標記爲(x,y,z,1);對於二維空間其變換矩陣是一個3X3的矩陣:;而三維空間的變換矩陣是一個4X4的矩陣:,具體的矩陣乘法怎麼計算的在這裏我就不講啦。函數
對於二維空間來講,各類變換矩陣以下:學習
(1)平移:,有: * = ;spa
(2)按比例縮放:,有 * = ;code
(3)旋轉:,該點繞原點O逆時針旋轉了θ角度。htm
(4)對稱:blog
以X軸對稱:,有 * = ;get
以Y軸對稱:,有 * = ;it
以原點O對稱:,有 * = ;
以Y=X對稱:,有 * = ;
以Y=-X對稱:,有 * = ;
(5)錯切:,有 * = ;
-------------------------------------------------------------下課啦---------------------------------------------------------------
接下來,yogurt說一下程序的總體思路就直接上代碼啦:
首先在主函數裏,是用戶依次輸入原始矩形的四個點後,程序會將該原始矩形繪製出來;而後根據用戶輸入的變換需求,程序進入到不一樣的變換函數中。每個變換函數會根據本身的變換性質提示用戶輸入控制變換的數據,而後程序生成對應的變換矩陣,將矩形的每個點與變換矩陣作矩陣乘法便可獲得每個點在變換後的座標。最後根據變換後的座標畫出變換後的矩陣便可。
代碼以下:(我直接使用了我老師給的畫圖程序,"Graph.cpp」)
// bianhuan.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #include"Graph.h" #include<math.h> #define PI 3.1415926 typedef struct POint { int a[3]; }point; point change(point p, int a[3][3]) { int b[3] = { 0, 0, 0 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) b[i] += p.a[j] * a[j][i]; } p.a[0] = b[0]; p.a[1] = b[1]; p.a[2] = b[2]; return p; } point change2(point p, double a[3][3]) { double b[3] = { 0, 0, 0 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) b[i] += p.a[j] * a[j][i]; } p.a[0] = b[0]; p.a[1] = b[1]; p.a[2] = b[2]; return p; } void DrawXY() { setPenColor(WHITE); moveTo(0, 0); lineTo(230, 0); drawText(200, 0,"230"); moveTo(0, 0); lineTo(0, 230); drawText(0, 230, "230"); return; } void DrawRectangle(point p1, point p2, point p3, point p4) { setPenColor(0xFF00); //須要注意一下變換點輸入順序也要能夠畫出矩形來 moveTo(p1.a[0], p1.a[1]); lineTo(p2.a[0], p2.a[1]); lineTo(p3.a[0], p3.a[1]); lineTo(p4.a[0], p4.a[1]); lineTo(p1.a[0], p1.a[1]); return; } void DrawChange(point p1, point p2, point p3, point p4, int a[3][3]) { point p11 = change(p1, a); point p22 = change(p2, a); point p33 = change(p3, a); point p44 = change(p4, a); clearWindow(); DrawXY(); DrawRectangle(p11, p22, p33, p44); return; } void DrawChange2(point p1, point p2, point p3, point p4, double a[3][3]) { point p11 = change2(p1, a); point p22 = change2(p2, a); point p33 = change2(p3, a); point p44 = change2(p4, a); clearWindow(); DrawXY(); DrawRectangle(p11, p22, p33, p44); return; } void Translation(point p1, point p2, point p3, point p4) { int tx, ty; printf("Please enter the change of x and y(格式:dx dy):"); scanf("%d %d", &tx, &ty); int a[3][3] = { 1, 0, 0, 0, 1, 0, tx, ty, 1 }; DrawChange(p1, p2, p3, p4, a); return; } void Scale(point p1, point p2, point p3, point p4) { int sx, sy; printf("Please enter the change of x and y(格式:dx dy):"); scanf("%d %d", &sx, &sy); int a[3][3] = { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; DrawChange(p1, p2, p3, p4, a); return; } void Rotation(point p1, point p2, point p3, point p4) { double d; printf("Please enter the angel of rotation:(格式:60度就輸入60):"); scanf("%lf", &d); getchar(); d = d / 180 * 1.0 * PI; double a[3][3] = { cos(d), -sin(d), 0, sin(d), cos(d), 0, 0, 0, 1 }; DrawChange2(p1, p2, p3, p4, a); return; } void Symmetry(point p1, point p2, point p3, point p4) { char mark; printf("Please enter the change:(以什麼爲中心作對稱,輸入:x/y/o(原點)/a(y=x)/b(y=-x))"); scanf("%c", &mark); getchar(); int a[3][3] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; switch (mark) { case'x': a[1][1] = -1; DrawChange(p1, p2, p3, p4, a); break; case'y': a[0][0] = -1; DrawChange(p1, p2, p3, p4, a); break; case'o': a[0][0] = a[1][1] = -1; DrawChange(p1, p2, p3, p4, a); break; case'a': a[0][0] = a[1][1] = 0; a[0][1] = a[1][0] = 1; DrawChange(p1, p2, p3, p4, a); break; case'b': a[0][0] = a[1][1] = 0; a[0][1] = a[1][0] = -1; DrawChange(p1, p2, p3, p4, a); break; default: break; } return; } void Shear(point p1, point p2, point p3, point p4) { int b, c; printf("Please enter the change of x and y(格式:dx dy):"); scanf("%d %d", &b, &c); int a[3][3] = { 1, b, 0, c, 1, 0, 0, 0, 1 }; DrawChange(p1, p2, p3, p4, a); } int _tmain(int argc, _TCHAR* argv[]) { point p1, p2, p3, p4; char order; printf("Please enter four point coordinationa(格式:x1,y1 x2,y2 x3,y3 x4,y4):\n"); scanf("%d,%d %d,%d %d,%d %d,%d", &p1.a[0], &p1.a[1], &p2.a[0], &p2.a[1], &p3.a[0], &p3.a[1], &p4.a[0], &p4.a[1]); p1.a[2] = p2.a[2] = p3.a[2] = p4.a[2] = 1; DrawXY(); DrawRectangle(p1, p2, p3, p4); getchar(); while (1) { printf("Please enter your control order:(平移:p,比例縮放:b,旋轉:x,對稱:d,錯切:c,退出:q)"); scanf("%c", &order); getchar(); switch (order) { case'p':Translation(p1, p2, p3, p4); break; case'b':Scale(p1, p2, p3, p4); break; case'x':Rotation(p1, p2, p3, p4); break; case'd':Symmetry(p1, p2, p3, p4); break; case'c':Shear(p1, p2, p3, p4); break; case'q':return 0; default: break; } } return 0; }
咱們來看看結果,驗證一下代碼的正確性吧:
一、用戶輸入矩形座標:
,程序畫出原始矩形:
二、輸入變換需求並進行變換:
(1)平移:
,結果:
(2)按比例縮放:
,結果:
(3)旋轉:
,結果:
(4)對稱:
以X軸作對稱:
以Y軸作對稱:
以原點作對稱:
以Y=X作對稱:
以Y=-X作對稱:
(5)錯切:
,結果: