【计算机图形学实验四——简单几何形体的平移、缩放、旋转等几何变换】

一、实验内容、目的、要求

1、简单几何形体(三角形、多边形等)的平移、缩放、旋转等几何变换。
2、掌握相关算法的原理及实现
3、实现基础代码(非调用OpenGL等图形库);
缩放、旋转等能指定变换参考点;
图形化交互;
其他类型的几何变换(不限于讲义内容);

二、c++源代码

#include<gl/glut.h>
#include<iostream>
#include<cmath>
#include<vector>
#define PI 3.14
#define TRANSLATE 0   //平移
#define DRAWPOLYGON 1 //绘制
#define ROTATE 2      //旋转
#define SCALE 3       //缩放
int tran_x, tran_y;//平移变量
int suo_x, suo_y;//缩放变量
int mode = DRAWPOLYGON;//默认为绘制模式
using namespace std;
struct position {
    double x;
    double y;
};
typedef float Matrix3x3[3][3];
Matrix3x3 matComposite;//复合矩阵
vector<position> xy;
position tmp;
void DrawPolygon();
void dragmouse(int x, int y);
void mymouse(int button, int state, int x, int y);
void myKeyboard(unsigned char key, int x, int y);
void myKeyboardUp(unsigned char key, int x, int y);
//设置为单位矩阵
void matrix3x3SetIdentity(Matrix3x3 mat) {
    int row, col;
    for (row = 0; row < 3; row++) {
        for (col = 0; col < 3; col++)
            mat[row][col] = (row == col);
    }
}

//矩阵相乘
void matrixMul(Matrix3x3 m1, Matrix3x3 m2) {
    int row, col;
    Matrix3x3 tmp;
    for (row = 0; row < 3; row++) {
        for (col = 0; col < 3; col++) {
            tmp[row][col] = m1[row][0] * m2[0][col] + m1[row][1] *
                m2[1][col] + m1[row][2] * m2[2][col];
        }
    }
    for (row = 0; row < 3; row++) {
        for (col = 0; col < 3; col++) {
            m2[row][col] = tmp[row][col];
        }
    }
}
//1、平移
void translate2D(float tx, float ty) {
    Matrix3x3 matTransl;
    matrix3x3SetIdentity(matTransl);//设置为单位矩阵
    matTransl[0][2] = tx;
    matTransl[1][2] = ty;
    matrixMul(matTransl, matComposite);

}
//2、旋转
void rotate2D(int x, int y, float theta) {
    theta = theta / 180 * PI;
    Matrix3x3 matRot;
    matrix3x3SetIdentity(matRot);
    matRot[0][0] = cos(theta);
    matRot[0][1] = -sin(theta);
    matRot[0][2] = x * (1 - cos(theta)) + y * sin(theta);
    matRot[1][0] = sin(theta);
    matRot[1][1] = cos(theta);
    matRot[1][2] = y * (1 - cos(theta)) - x * sin(theta);
    matrixMul(matRot, matComposite);
}

//3、缩放
void scale2D(float sx, float sy, int x, int y) {
    Matrix3x3 matScale;
    matrix3x3SetIdentity(matScale);
    matScale[0][0] = sx;
    matScale[0][2] = (1 - sx) * x;
    matScale[1][1] = sy;
    matScale[1][2] = (1 - sy) * y;
    matrixMul(matScale, matComposite);
}
//复合矩阵
void transformVerts2D() {
    float tmp;
    for (int i = 0; i < xy.size(); i++) {
        tmp = matComposite[0][0] * xy[i].x + matComposite[0][1] * xy[i].y + matComposite[0][2];
        xy[i].y = matComposite[1][0] * xy[i].x + matComposite[1][1] * xy[i].y + matComposite[1][2];
        xy[i].x = tmp;
    }
    DrawPolygon();
    matrix3x3SetIdentity(matComposite);
}


//绘制多边形
void DrawPolygon() {
    glPolygonMode(GL_BACK, GL_LINE);//设置反面为线性模式
    glPolygonMode(GL_FRONT, GL_LINE);//设置正面为线性模式
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POLYGON);
    for (unsigned int i = 0; i < xy.size(); i++) {
        glVertex2f(xy[i].x, xy[i].y);
    }
    glEnd();
    glFlush();
}

//鼠标拖动
void dragmouse(int x, int y) {
    float ssx = 1, ssy = 1;
    switch (mode)
    {
    case TRANSLATE:
        translate2D(x - tran_x, y - tran_y);
        transformVerts2D();
        tran_x = x;
        tran_y = y;
        break;
    case DRAWPOLYGON:

        break;
    case ROTATE:
        if (x <= suo_x && y >= suo_y)
            rotate2D(tran_x, tran_y, -8);
        else
            rotate2D(tran_x, tran_y, 8);
        transformVerts2D();
        suo_x = x;
        suo_y = y;
        break;
    case SCALE:

        /*不等比例缩放*//*
        if (x > _xtmp) {
            ssx += 0.01f;
        }
        else if (x < _xtmp && ssx>0) {
            ssx -= 0.01f;
        }
        if (y < _ytmp) {
            ssy += 0.01f;
        }
        else if (y > _ytmp && ssy > 0) {
            ssy -= 0.01f;
        }*/

        //等比例缩放
        if(x<= suo_x &&y>= suo_y){
            ssx-=0.01f;
            ssy-=0.01f;
        }else{
            ssx+=0.01f;
            ssy+=0.01f;
        }

        scale2D(ssx, ssy, tran_x, tran_y);
        transformVerts2D();
        suo_x = x;
        suo_y = y;
        break;
    default:
        break;
    }

}

//鼠标监听
void mouse(int button, int state, int x, int y) {

    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        switch (mode)
        {
            //q,w,e,r
        case TRANSLATE:
            tran_x = x;
            tran_y = y;

            break;
        case DRAWPOLYGON:
            tmp.x = x;
            tmp.y = y;
            xy.push_back(tmp);
            DrawPolygon();
            break;
        case ROTATE:
            tran_x = x;
            tran_y = y;
            suo_x = x;
            suo_y = y;
            break;
        case SCALE:
            tran_x = x;
            tran_y = y;
            break;
        default:
            break;
        }

    }

}
//键盘监听
void Keyboard(unsigned char key, int x, int y) {
    //清空删除
    if (key == 'a') {
        glClear(GL_COLOR_BUFFER_BIT);//清除窗口显示内容
        glFlush();
        xy.clear();
    }

}

void KeyboardUp(unsigned char key, int x, int y) {
    switch (key)
    {
    case 'q':mode = TRANSLATE;
        break;
    case 'w':mode = DRAWPOLYGON;
        break;
    case 'e':mode = ROTATE;
        break;
    case 'r':mode = SCALE;
        break;
    default:
        break;
    }
}
void display() {
    glFlush();
}
void menu(int id) {
    if (id == 0)
        mode = 0;
    else if (id == 1)
        mode = 1;
    else if (id == 2)
        mode = 2;
    else if (id == 3)
        mode = 3;
}
//主函数
int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitWindowPosition(200, 100);
    glutInitWindowSize(400, 400);
    glutCreateWindow("几何图形的平移、旋转、绘制变换");//创建窗口
    int id = glutCreateMenu(menu);
    glutAddMenuEntry("平移", 0);
    glutAddMenuEntry("绘制", 1);
    glutAddMenuEntry("旋转", 2);
    glutAddMenuEntry("缩放", 3);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    glClearColor(0, 0, 0, 0);//设置窗口颜色为黑色
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0, 0, 1);//设置颜色为蓝色
    gluOrtho2D(0, 500, 400, 0);//坐标系以左上方为原点
    matrix3x3SetIdentity(matComposite);
    glutDisplayFunc(display);
    glutMouseFunc(mouse);//鼠标监听回调函数
    glutMotionFunc(dragmouse);//鼠标拖动
    glutKeyboardFunc(Keyboard);//键盘监听
    glutKeyboardUpFunc(KeyboardUp);//键盘弹起状态
    glutMainLoop();
}



三、运行截图

1、三角形
在这里插入图片描述
2、五角星
在这里插入图片描述
以上我是用vs2019+opengl运行的,可以正确运行。

参考文章:二维图形学的变换-平移、旋转、缩放 OpenGL

  • 6
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值