一、實(shí)現(xiàn)方案
對(duì)于一個(gè)二維圖形作平移、旋轉(zhuǎn)、放縮變換,可以轉(zhuǎn)換為在二維坐標(biāo)系中圖形的所有點(diǎn)分別可以對(duì)應(yīng)到在x,y軸方向分別平移tx,ty(平移)、繞一點(diǎn)旋轉(zhuǎn)固定的角(旋轉(zhuǎn))、在x,y軸方向分別放縮sx,sy倍。
對(duì)于變換的原理,只需要將原圖形的點(diǎn)通過(guò)極坐標(biāo)或者相加、相乘,再結(jié)合二維矩陣的原理即可實(shí)現(xiàn),如果圖形需要對(duì)圖形對(duì)象進(jìn)行旋轉(zhuǎn)和放縮兩類變換進(jìn)行多次操作,則可以首先將兩變換矩陣合成一個(gè)復(fù)合變換矩陣。針對(duì)于平移是矩陣的相加,為了統(tǒng)一成相乘,可以用齊次坐標(biāo)可以解決。
如下為在齊次坐標(biāo)下,各原點(diǎn)與變換矩陣形式。
所以,若要完成更復(fù)雜的變換,可以通過(guò)將這些基本變換合成一個(gè)復(fù)合變換,將多次運(yùn)算轉(zhuǎn)換成的一次性矩陣與向量相乘即可完成復(fù)雜變換。
如任一圖形關(guān)于任意的反射軸y=a+bx的反射變換,可以轉(zhuǎn)換為(1)平移-a;(2)旋轉(zhuǎn)至與x/y軸重合;(3)沿x/y軸對(duì)稱;(3)旋轉(zhuǎn)回(2)之前的位置;(4)平移a四步即可完成。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-505192.html
二、代碼實(shí)現(xiàn)
// CMatrixView 繪圖
//變換矩陣
struct Matrix {
double a[10][10];
Matrix() {
memset(a, 0, sizeof(a));
}
void init(){
for (int i = 0; i <= 4; i++) {
a[i][i] = 1;
}
}
};
//坐標(biāo)點(diǎn)
struct Point
{
double x, y;
};
//矩陣相乘
Matrix get_mx(Matrix a, Matrix b) {
Matrix tmp;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
double sum=0;
for (int k = 0; k < 3; k++){
sum += a.a[i][k] * b.a[k][j];
}
tmp.a[i][j] = sum;
}
}
return tmp;
}
//得到與矩陣相乘后的點(diǎn)
Point matrix_point(Point p, Matrix m) {
Matrix n;
n.a[0][0] = p.x;
n.a[1][0] = p.y;
n.a[2][0] = 1;
for (int i = 0; i < 3; i++) {
double sum = 0;
for (int j = 0; j < 3; j++) {
sum+= m.a[i][j] * n.a[j][0];
}
n.a[i][1] = sum;
}
p.x = n.a[0][1] / n.a[2][1];
p.y = n.a[1][1] / n.a[2][1];
return p ;
}
//平移
Matrix translate(double Tx, double Ty, Matrix m) {
Matrix tmp;
tmp.init();
tmp.a[0][2] = Tx;
tmp.a[1][2] = Ty;
tmp = get_mx(m, tmp);
return tmp;
}
//放縮
Matrix Shrink(double Tx, double Ty, Matrix m){
Matrix tmp;
tmp.init();
tmp.a[0][0] = Tx;
tmp.a[1][1] = Ty;
tmp = get_mx(m, tmp);
return tmp;
}
//旋轉(zhuǎn)
Matrix revolve(double cot, Matrix m) {
Matrix tmp;
tmp.init();
tmp.a[0][0] = cos(cot);
tmp.a[1][1] = cos(cot);
tmp.a[0][1] = -(sin(cot));
tmp.a[1][0] = sin(cot);
tmp = get_mx(m, tmp);
return tmp;
}
//軸對(duì)稱
Matrix axisymmetric(int x, Matrix m) {
Matrix tmp;
tmp.init();
//x==1為x軸對(duì)稱
if (x == 1) {
tmp.a[1][1] = -1;
}
//否則為y軸對(duì)稱
else {
tmp.a[0][0] = -1;
}
tmp = get_mx(m, tmp);
return tmp;
}
//關(guān)于任意軸對(duì)稱
Matrix symmetry(double k, double b, Matrix m) {
Matrix tmp;
tmp.init();
//先平移
double cot = atan(k);
tmp = translate(0, -b, tmp);
//再旋轉(zhuǎn)
tmp = revolve(cot, tmp);
//再沿x軸對(duì)稱
tmp = axisymmetric(1, tmp);
//再旋轉(zhuǎn)
tmp = revolve(-cot, tmp);
//再平移
tmp = translate(0, b, tmp);
tmp = get_mx(m, tmp);
return tmp;
}
void Line(CDC* pDC, Point p1, Point p2) {
pDC->MoveTo(p1.x, p1.y);
pDC->LineTo(p2.x, p2.y);
}
void Linepoly(CDC* pDC, Point p1, Point p2,Point p3,int color) {
CPen m_newPen, * m_oldPen;
//創(chuàng)建新畫筆
m_newPen.CreatePen(PS_SOLID, 3,color);
//將新畫筆選入設(shè)備上下文,并且保存舊畫筆
m_oldPen = pDC->SelectObject(&m_newPen);
pDC->MoveTo(p1.x, p1.y);
pDC->LineTo(p2.x, p2.y);
pDC->MoveTo(p2.x, p2.y);
pDC->LineTo(p3.x, p3.y);
pDC->MoveTo(p3.x, p3.y);
pDC->LineTo(p1.x, p1.y);
pDC->SelectObject(m_oldPen);
}
//實(shí)現(xiàn)程序:
//沿任意軸對(duì)稱
Point p7 = { -10,10 };
Point p8 = { -90,90 };
Point p9 = { -20,50 };
//變換前為棕紅色
Linepoly(pDC, p7, p8, p9,RGB(128,0,0));
Point p10 = { -100,-100 };
Point p11 = {100,100};
Line(pDC, p10, p11);
Matrix m4;
m4.init();
m4 = symmetry(1, 0, m4);
p7 = matrix_point(p7, m4);
p8 = matrix_point(p8, m4);
p9 = matrix_point(p9, m4);
//變換后為藍(lán)色
Linepoly(pDC, p7, p8, p9,RGB(0,51,153));
三、代碼運(yùn)行結(jié)果
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-505192.html
到了這里,關(guān)于計(jì)算機(jī)圖形學(xué):二維圖形的幾何變換(算法原理及代碼實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!