实验目的: 掌握相关算法的原理及实现
实验要求: 实现基础代码(非调用OpenGL等图形库); 缩放、旋转等能指定变换参考点; 图形化交互;
其他(可选): 其他类型的几何变换(不限于讲义内容); 用OpenGL或者其他程序包实现
以下代码仅供参考:
#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();
}