圖形學基礎(二)圖形變換_上:2D 基本變換/複合變換

C++,MFC模板,VS2017算法

準備(2D圖形、矩陣、座標系)函數

typedef double array2d[5][5];
typedef double array[24];
class CMyClass
{
public:
    int xx, yy;//屏幕
    array X, Y, Z, C;
    array2d A1, A;//矩陣 public:
    CMyClass();
    virtual ~CMyClass();void Calculate(array2d B);//矩陣計算 void Display();//顯示 void DrawView(CDC* pdc, CRect rr);//在座標系內畫圖 void moveto(double x, double y, CDC* pdc);
    void lineto(double x, double y, CDC* pdc);
    void cleanB(array2d B);//矩陣復位
};

 

一、2D圖形spa

(可以使用CDC類的成員函數GetMapMode和SetMapMode來得到和設置當前映射模式:code

  int GetMapMode( ) const; // 返回當前的映射模式視頻

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

在默認映射模式(MM_TEXT)下:教程

代碼(給到了初始化):io

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;
}

 

二、矩陣模板

矩陣計算:class

void CMyClass::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];
    }
}

矩陣清零:

void CMyClass::cleanB(array2d B)
{
    int i, j;
    for (i = 1; i <= 3; ++i) {
        for (j = 1; j <= 3; ++j) {
            B[i][j] = 0;
        }
    }
}

 

三、座標系

以屏幕中點爲原點,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();
}

 

基本變換(平移、旋轉、縮放、對稱)

(兩種矩陣表示方式)如下采用第一種表示方式:

一、平移

 只改變矩陣 [3] [1],[3] [2] 位置的值便可:

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

void CGeoTrans2DView::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();
}

 

二、旋轉

只改變矩陣 [1] [1],[1] [2],[2] [1],[2] [2] 位置的值:

 

逆時針旋轉30°

void CGeoTrans2DView::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();
}

 

三、縮放

 該代碼沒有對Z進行處理,因此此處用下面的一種方法(有誤:應該是放大 1/x 倍),是不可行的

void CGeoTrans2DView::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();
}

 

四、對稱

 x軸對稱

void CGeoTrans2DView::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();
}

 

複合變換(級聯)

級聯變換:一種以上的基本變換

一、非原點縮放

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

void CGeoTrans2DView::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();
}

 

二、非原點旋轉 

 繞(0,40)旋轉60°

void CGeoTrans2DView::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();
}

 

參考資料:

一、《計算機圖形學原理及算法教程》和青芳 編著

二、計算機圖形學 - 中國農業大學 趙明老師視頻 

 

本文采用CC BY 4.0知識共享許可協議。

相關文章
相關標籤/搜索