# 二维图形变换:

## 基础:

https://blog.csdn.net/zhuiqiuzhuoyue583/article/details/95228010

• 平移
• 缩放
• 旋转

## 二维图形变换样例: 时钟

### 源码:

#define NDEBUG
#ifndef GLUT_DISABLE_ATEXIT_HACK
#define GLUT_DISABLE_ATEXIT_HACK
#endif
#include <windows.h>
#include <gl/glut.h>
#include <math.h>
#include <stdio.h>
#include <vector>

using namespace std;

const int windowWidge=600, windowHeight=600;

void setPixel(GLint xCoord, GLint yCoord){
glBegin (GL_POINTS);
glVertex2i (xCoord, yCoord);
glEnd();
}

//---------------------------------------------
// Bresenham 画圆
class screenPt {
private:
GLint x, y;

public:
screenPt() { x = y = 0; }
void setCoords(GLint xCoordValue, GLint yCoordValue) {
x = xCoordValue;
y = yCoordValue;
}
GLint getx() const { return x; }
GLint gety() const { return y; }
void incremetx() { x++; }
void decrementy() { y--; }
};

void circleMidp(GLint xc, GLint yc, GLint radius) {
screenPt circPt;
GLint p = 1 - radius;
circPt.setCoords(0, radius);
void circlePlotPoints(GLint, GLint, screenPt);
circlePlotPoints(xc, yc, circPt);
while (circPt.getx() < circPt.gety()) {
circPt.incremetx();
if (p < 0)
p += 2 * circPt.getx() + 1;
else {
circPt.decrementy();
p += 2 * (circPt.getx() - circPt.gety()) + 1;
}
circlePlotPoints(xc, yc, circPt);
}
}
void circlePlotPoints(GLint xc, GLint yc, screenPt circPt) {
setPixel(xc + circPt.getx(), yc + circPt.gety());
setPixel(xc - circPt.getx(), yc + circPt.gety());
setPixel(xc + circPt.getx(), yc - circPt.gety());
setPixel(xc - circPt.getx(), yc - circPt.gety());
setPixel(xc + circPt.gety(), yc + circPt.getx());
setPixel(xc - circPt.gety(), yc + circPt.getx());
setPixel(xc + circPt.gety(), yc - circPt.getx());
setPixel(xc - circPt.gety(), yc - circPt.getx());
}

//---------------------------------------------
//组合模型变换: 时钟

const GLfloat PI = 3.141592653f;

// 显示的时间，时 分 秒
float h = 0.0f;
float m = 0.0f;
float s = 0.0f;

//定时器回调函数:
void timerFunc(int value){
//设置时分秒针
s += 1;
int carry1 = 0;
if (s >= 60){
s = 0;
carry1 = 1;
}
m += carry1;
int carry2 = 0;
if (m >= 60){
m = 0;
carry2 = 1;
}
h += carry2;
if (h >= 24){
h = 0;
}

//  重绘
glutPostRedisplay();

glutTimerFunc(1000, timerFunc, 1); // 每1000ms中执行一次

return ;
}

//绘制函数
void clockDisplay(){

// 用当前清除色清除颜色缓冲区，即设定窗口的背景色
glClear(GL_COLOR_BUFFER_BIT);

// 黑色
glColor3f(0.1f, 0.2f, 0.1f);

// 绘制时钟外边框
int cx=windowWidge/2, cy=windowHeight/2;
int R=150;
circleMidp (cx, cy, R);		//这里用的 Bresenham 画圆
circleMidp (cx, cy, R-3);

//绘制时钟刻度:
int lineNum=60;
int w1=5, w2=2;
float len1=10, len2=5;
for(int i=0;i<lineNum;++i){
//12条粗线
if(i%5==0){
glLineWidth(w1);
//glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINES);
glVertex2f(cx + (R - len1)*sin(2 * PI / lineNum * i), cy + (R - len1)*cos(2 * PI / lineNum * i));
glVertex2f(cx + R*sin(2 * PI / lineNum * i), cy + R*cos(2 * PI / lineNum * i));
glEnd();
}
//其余细线
else{
glLineWidth(w2);  //其他的刻度
//glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINES);
glVertex2f(cx + (R - len2)*sin(2 * PI / lineNum * i), cy + (R - len2)*cos(2 * PI / lineNum * i));
glVertex2f(cx + R*sin(2 * PI / lineNum * i), cy + R*cos(2 * PI / lineNum * i));
glEnd();
}
}

//绘制时钟中心点
int dotWidth=3;
for(int i=1;i<=dotWidth;++i){
circleMidp (cx, cy, i);
}

//绘制时分秒针
int hLen=R-len1-50;
int mLen=R-len1-25;
int sLen=R-len1-5;

//12小时制
int h12= h >= 12 ? (h - 12) : h;
float sAngle=s/60.0;
float mAngle=(m * 60 + s) / 3600.0;
float hAngle=(h12 * 60 * 60 + m * 60 + s) / (12 * 60 * 60);

// 秒
glLineWidth(1);
glBegin(GL_LINES);
glVertex2f(cx, cy);
glVertex2f(cx + sLen*sin(2 * PI*sAngle), cy + sLen*cos(2 * PI*sAngle));
glEnd();

// 分
glLineWidth(3);
glBegin(GL_LINES);
glVertex2f(cx, cy);
glVertex2f(cx + mLen*sin(2 * PI*mAngle), cy + mLen*cos(2 * PI*mAngle));
glEnd();

// 时
glLineWidth(5);
glBegin(GL_LINES);
glVertex2f(cx, cy);
glVertex2f(cx + hLen*sin(2 * PI*hAngle), cy + hLen*cos(2 * PI*hAngle));
glEnd();

glFlush ();
return ;
}

//---------------------------------------------

//初始化绘制
void init(){
glClearColor(1.0,1.0,1.0,0.0);//清除颜色设置
glMatrixMode(GL_PROJECTION);//设置投影方式

//获取本地时间
SYSTEMTIME sys;
GetLocalTime(&sys);
h = sys.wHour;
m = sys.wMinute;
s = sys.wSecond;

gluOrtho2D (0.0,windowWidge*1.0,0.0,windowHeight*1.0);
return ;
}

int main(int argc, char** argv){
glutInit(&argc, argv);//初始化glut
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//设置显示模式为单缓冲，RGB模式
glutInitWindowPosition(0,0);//设置窗口位置
glutInitWindowSize(windowWidge,windowHeight);//设置窗口大小
glutCreateWindow("时钟");//设置窗口标题
init();
glutDisplayFunc(clockDisplay);
glutTimerFunc(1000, timerFunc, 1);
glutMainLoop();
return 0;
}



### 源码分析:

1. 定时器:

注册一个函数, 间隔一定时间再执行, 只执行一次, 所以源码中在调用函数中又添加了glutTimerFunc()

glutTimerFunc(unsigned int msecs,void(*func)(int value),int value)

• msecs
在调用func函数之前要等待的时间（单位：毫秒）

• func
注册一个调用函数，在等待msecs毫秒之后执行

注意func的返回值为void, 参数为int

• value
作为参数传递给func

07-25 68
07-21 2403
02-27 1万+
11-21
07-01 2512
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客