# openGL笔记-画基本图形

#include "iostream"
#include <GL/glut.h>
#include<cmath>
#include<vector>
#include<algorithm>
#include<fstream>
#include "MatrixV.h"

#define PI acos(-1)
using namespace std;
#pragma comment(lib, "legacy_stdio_definitions.lib")

// ---------------------------------------------------------------------------------------------------结构
struct MPOINT {
GLdouble x, y;
MPOINT() {

}
MPOINT(double x, double y) {
this->x = x;
this->y = y;
}
bool operator == (struct MPOINT& a) {
return (abs(this->x - a.x<=2)) && (abs(this->y - a.y)<=2);
}
friend ostream& operator<<(ostream &out,struct MPOINT& a) {
cout << a.x << " " << a.y << endl;
return out;
}
};
struct lineEquation {
double k, b;
int x1, x2, y1, y2;
bool fk;//true 代表k不存在
};

struct Color {
GLdouble r, g, b;
struct Color(GLdouble r, GLdouble g, GLdouble b)
{
this->r = r;
this->g = g;
this->b = b;
}
};

vector<struct lineEquation> lineEV;
typedef struct LineAE    /*有效边描述结构*/
{
GLfloat x;          /*当前扫描线与边的交点 */
GLfloat dx;         /*斜率的倒数*/
GLint ymax;          /*边所在的最大扫描线值*/
struct LineAE *next;  /*指向下一条有效边*/
LineAE() {
next = NULL;
}
}ActiveEdge;

vector<ActiveEdge> activeEdge;
struct MPOINT *oldPoint, *curPoint;
GLdouble longAxes, shortAxes,ovalAngle;//输入为角度，计算时转化为弧度
int flag = 0,choice ;
vector<struct MPOINT> vertexSet;
void Line_sin()
{
glClear(GL_COLOR_BUFFER_BIT);
//glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_LINES);
{
glVertex2f(-1.0f, 0.0f);
glVertex2f(1.0f, 0.0f);         // 以上两个点可以画x轴
glVertex2f(0.0f, -1.0f);
glVertex2f(0.0f, 1.0f);         // 以上两个点可以画y轴
}
glEnd();
glBegin(GL_LINE_STRIP);
{
for (int i = 0; i < 1000; i++) {
glVertex2f(i, 100*sin(i*1.0));
}
}
glEnd();
glFlush();
}

void Show()
{
const GLfloat factor = 0.1f;
GLfloat x;
glClear(GL_COLOR_BUFFER_BIT);
//glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINES);
{
glVertex2f(-1.0f, 0.0f);
glVertex2f(1.0f, 0.0f);         // 以上两个点可以画x轴
glVertex2f(0.0f, -1.0f);
glVertex2f(0.0f, 1.0f);         // 以上两个点可以画y轴
}
glEnd();
glBegin(GL_POINTS);
{
for (x = -1.0f / factor; x < 1.0f / factor; x += 0.01f)
{
glVertex2f(x*factor, sin(x)*factor);
}
}
glEnd();
glFlush();
}

/* 函数用来画图 */
void display(void)
{

}

//-------------------------------------------------------------------------------------------------------直线
//1.DDA
void Line_DDA(struct MPOINT* p1, struct MPOINT* p2)
{
//glClear(GL_COLOR_BUFFER_BIT);
//glColor3f(1.0f, 0.0f, 0.0f);
//glPointSize(5);//设置点大小为5像素

GLdouble Xa = p1->x, Ya = p1->y, Xb = p2->x, Yb = p2->y;
GLint dx = Xb - Xa, dy = Yb - Ya, steps, k;
GLdouble xIncrement, yIncrement, x = Xa, y = Ya;
if (abs(dx) > abs(dy))
steps = abs(dx);
else
steps = abs(dy);
xIncrement = dx / (GLdouble)steps;
yIncrement = dy / (GLdouble)steps;
glBegin(GL_POINTS);
{
glVertex2d((GLdouble)round(x), (GLdouble)round(y));
for (k = 0; k < steps; k++)
{
x += xIncrement;
y += yIncrement;
glVertex2d((GLdouble)round(x), (GLdouble)round(y));
}
}
glEnd();
glFlush();
}

//中点Bresenham算法（改进版）
void Line_Bresenham(struct MPOINT* p1, struct MPOINT* p2)
{
GLint dx = p2->x - p1->x, dy = p2->y - p1->y,x = p1->x, y= p1->y,e=0;
GLdouble k = (dy) / (GLdouble)dx;
glBegin(GL_POINTS);
{
glVertex2i(round(x), round(y));
if (k >= 0) {
if (p1->x > p2->x || ((p1->x == p2->x) &&(p1->y > p2->y))) {
GLint tmp = p1->x;
x = p2->x;
p2->x = tmp;
tmp = p1->y;
y  = p2->y;
p2->y = tmp;
dx *= -1;
dy *= -1;
}
if (k <= 1)
{
e = -dx;
while (x != p2->x && y != p2->y) {
e += 2 * dy;
if (e > 0) {
if (x < p2->x || y< p2->y) {
x++;
y++;
}
else if (x > p2->x || y > p2->y)
{
x--;
y--;
}
e -= 2 * dx;
}
else {
if (x < p2->x) {
x++;
}
else if(x > p2->x)
{
x--;
}
}
glVertex2i(round(x), round(y));
}
}
else if (k > 1) {
e = -dy;
while (x != p2->x && y != p2->y) {
e += 2 * dx;
if (e > 0) {
if (x < p2->x || y< p2->y) {
x++;
y++;
}
else if (x > p2->x || y > p2->y)
{
x--;
y--;
}
e -= 2 * dy;
}
else {
if (y < p2->y) {
y++;
}
else if (y > p2->y)
{
y--;
}
}
glVertex2i(round(x), round(y));
}
}
}
else {
if (k >= -1)
{
e = -dx;
while (x != p2->x && y != p2->y) {
e += abs(dy)*2;
if (e > 0) {
if (x > p2->x || y< p2->y) {
x--;
y++;
}
else if (x < p2->x || y > p2->y)
{
x++;
y--;
}
e -= abs(dx)*2;
}
else {
if (x < p2->x) {
x++;
}
else if (x > p2->x)
{
x--;
}
}
glVertex2i(round(x), round(y));
}

}
else
{
e = -dy;
while (x != p2->x && y != p2->y) {
e += 2 * abs(dx);
if (e > 0) {
if (x > p2->x || y< p2->y) {
x--;
y++;
}
else if (x < p2->x || y > p2->y)
{
x++;
y--;
}
e -= 2 * abs(dy);
}
else {
if (y < p2->y) {
y++;
}
else if (y > p2->y)
{
y--;
}
}
glVertex2i(round(x), round(y));
}
}
}
}
glEnd();
glFlush();
}

//-------------------------------------------------------------------------------------------------------圆形
//极坐标法 for Ciecle
void Circle_Polar(struct MPOINT *c, GLdouble R)
{
GLint n = 100;
GLdouble x=c->x, y=c->y;
glBegin(GL_POINTS);
{
for (int i = 0; i < n; i++)
{
x =c->x + R * cos(2 * PI *i/ n);
y =c->y + R * sin(2 * PI *i/ n);
glVertex2f(x,y);
}
}
glEnd();
glFlush();
}
//中点Bresenham for Circle
//画点(x,y)和他的7个对称点
void Draw8(struct MPOINT *c,GLdouble x, GLdouble y)
{
GLdouble X = c->x, Y = c->y;
glBegin(GL_POINTS);
{
glVertex2d(x +X,y + Y);
glVertex2d(-x +X, y + Y);
glVertex2d(x + X, -y + Y);
glVertex2d(-x + X, -y + Y);

glVertex2d(y + X, x + Y);
glVertex2d(-y + X, x + Y);
glVertex2d(y + X, -x + Y);
glVertex2d(-y + X, -x + Y);
}
glEnd();
glFlush();
}
void Circle_Bresenham(struct MPOINT *c,GLdouble R)
{
GLdouble d = 1 - R, x = 0, y = R;
while (x <= y)
{
Draw8(c, x ,y);
if (d <= 0)
{
d += 2 * x + 3;
x++;
}
else
{
d += 2 * (x-y) + 5;
x++;
y--;
}
}
}

//DDA for Circle
void Circle_DDA(struct MPOINT *c, GLdouble R)
{
GLdouble xc = c->x, yc = c->y, x = xc + R, y = yc, theta = 0, e = 1 / R;
glBegin(GL_POINTS);
{
while (theta < 2 * PI) {
glVertex2f(x, y);
x = x - (y - yc)*e;
y = y + (x - xc)*e;
theta += e;
}
}
glEnd();
glFlush();
}

//-------------------------------------------------------------------------------------------------------椭圆
//某点绕某点旋转后的新坐标
void getNewPoint(struct MPOINT* c,GLdouble X, GLdouble Y,GLdouble& x,GLdouble& y)
{
x = (X - c->x)*cos(ovalAngle*PI / 180) - (Y - c->y)*sin(ovalAngle*PI / 180) + c->x;
y = (X - c->x)*sin(ovalAngle*PI / 180) + (Y - c->y)*cos(ovalAngle*PI / 180) + c->y;
}

//画点(x,y)和它的3个对称点
void Draw4(struct MPOINT* c,GLdouble x, GLdouble y,double pointSize, struct Color color)
{
GLdouble X = c->x, Y = c->y,xn,yn;
glColor3f(color.r, color.g, color.b);
glPointSize(pointSize);
glBegin(GL_POINTS);
{
/*
glVertex2f(x+X,y+Y);
glVertex2f(-x+X, y+Y);
glVertex2f(x+X, -y+Y);
glVertex2f(-x+X, -y+Y);
*/
getNewPoint(c,x + X, y + Y, xn, yn);
glVertex2f(xn, yn);
getNewPoint(c, -x + X, y + Y, xn, yn);
glVertex2f(xn, yn);
getNewPoint(c, x + X, -y + Y, xn, yn);
glVertex2f(xn, yn);
getNewPoint(c, -x + X, -y + Y, xn, yn);
glVertex2f(xn, yn);
}
glEnd();
glFlush();
}
//中点Bresenham算法 for Oval
void Oval_Bresenham(struct MPOINT* c,double pointSize, struct Color color)
{
if (longAxes <= 0 || shortAxes <= 0) {
longAxes = 50, shortAxes = 10;
}
GLdouble d = shortAxes * shortAxes + longAxes * longAxes*(0.25 - shortAxes), x = 0, y = shortAxes;
while (shortAxes*shortAxes*(x + 1) < longAxes * longAxes * (y - 0.5))
{
Draw4(c,x, y, pointSize,color);
if (d <= 0)
{
d += shortAxes * shortAxes *(2 * x + 3);
x++;
}
else
{
d += shortAxes * shortAxes *(2 * x + 3) + longAxes * longAxes *(-2 * y + 2);
x++;
y--;
}
}

d = shortAxes * shortAxes*(x + 0.5)*(x + 0.5) + longAxes * longAxes *(y - 1)*(y - 1) - longAxes * longAxes * shortAxes * shortAxes;
while (y >= 0)
{
Draw4(c,x,y, pointSize,color);
if (d <= 0)
{
d += shortAxes * shortAxes *(2*x + 2) + longAxes * longAxes *(-2*y + 3);
x++;
y--;
}
else
{
d += longAxes * longAxes *(-2*y + 3),
y--;
}
}
}

//======================================================= 多边形的扫描转换和区域填充 ===============

// 点集按序连线
void buildPloy(vector<struct MPOINT> vertexSet,double &ymin,double& ymax)
{

int len = vertexSet.size();
cout << "多边形边条数:\t" << len << endl;
/*
//划线1
glBegin(GL_LINES);
{
for (int i = 1; i < len; i++) {
cout << vertexSet[i].x << "  " << vertexSet[i].y << endl;
glVertex2i(vertexSet[i - 1].x, vertexSet[i - 1].y);
glVertex2i(vertexSet[i].x, vertexSet[i].y);
}
glVertex2i(vertexSet[0].x,vertexSet[0].y);
glVertex2i(vertexSet[len-1].x, vertexSet[len - 1].y);
}
glEnd();
glFlush();
*/
struct lineEquation tmpE;
ymin = vertexSet[0].y;
ymax = ymin;
//划线二
for (int i = 1; i < len; i++) {
//划线
Line_DDA(&vertexSet[i - 1], &vertexSet[i]);
// k不存在时 x = x1 = x2
if (abs((vertexSet[i - 1].x - vertexSet[i].x)) <1e-10 ) {
tmpE.fk = true;
}
else { // y = k*x +b
tmpE.fk = false;
tmpE.k = (double)(vertexSet[i - 1].y - vertexSet[i].y) / (double)(vertexSet[i - 1].x - vertexSet[i].x);
tmpE.b = vertexSet[i - 1].y - tmpE.k * vertexSet[i - 1].x;
// k == 0 时 y = b
}
// 求直线所占范围 xmin xmax ymin ymax
if (vertexSet[i - 1].x <= vertexSet[i].x) {
tmpE.x1 = vertexSet[i - 1].x;
tmpE.x2 = vertexSet[i].x;
}
else {
tmpE.x1 = vertexSet[i].x;
tmpE.x2 = vertexSet[i - 1].x;
}
if (vertexSet[i - 1].y <= vertexSet[i].y) {
tmpE.y1 = vertexSet[i - 1].y;
tmpE.y2 = vertexSet[i].y;
}
else {
tmpE.y1 = vertexSet[i].y;
tmpE.y2 = vertexSet[i - 1].y;
}
lineEV.push_back(tmpE);
// 更新扫描线
if (ymin > vertexSet[i].y) {
ymin = vertexSet[i].y;
}
if (ymax < vertexSet[i].y) {
ymax = vertexSet[i].y;
}
}
// 划线
Line_DDA(&vertexSet[0], &vertexSet[len-1]);
// k不存在时 x = x1 = x2
if (abs((vertexSet[0].x - vertexSet[len -1].x)) < 1e-10) {
tmpE.fk = true;
}
else {
tmpE.fk = false;
tmpE.k = (double)(vertexSet[0].y - vertexSet[len - 1].y) / (double)(vertexSet[0].x - vertexSet[len - 1].x);
tmpE.b = vertexSet[0].y - tmpE.k * vertexSet[0].x;
}
if (vertexSet[0].x <= vertexSet[len - 1].x) {
tmpE.x1 = vertexSet[0].x;
tmpE.x2 = vertexSet[len - 1].x;
}
else {
tmpE.x1 = vertexSet[len - 1].x;
tmpE.x2 = vertexSet[0].x;
}
if (vertexSet[0].y >= vertexSet[len -1].y) {
tmpE.y1 = vertexSet[len - 1].y;
tmpE.y2 = vertexSet[0].y;
}
else {
tmpE.y1 = vertexSet[0].y;
tmpE.y2 = vertexSet[len - 1].y;
}
lineEV.push_back(tmpE);
}

// 画点
void drawPoint(struct MPOINT& a,GLdouble pointSize,struct Color color) {
glColor3f(color.r, color.g, color.b);
glPointSize(pointSize);
glBegin(GL_POINTS);
{
glVertex2f(a.x,a.y);
}
glEnd();
glFlush();
}

bool cmp(struct LineAE& a,struct LineAE& b)
{
if (a.x != b.x) {
return a.x < b.x;
}
else {
return a.dx < b.dx;
}
}
//改进的有效边表算法（Y连贯性算法）
//求交点，排序（生成AE表）  匹配  填色
void buildAE(double ymin,double ymax)
{
int numLE = lineEV.size();
double x;
vector<ActiveEdge> lineAE;
ActiveEdge *tmpAE,*preAE;
activeEdge.clear();

//cout << "最小扫描线: "<<ymin << "\t最大扫描线：" << ymax << "\t扫描线数量: " << ymax - ymin << endl;
// 每条y
for (int i = ymin; i <= ymax; i++) {
lineAE.clear();
int t = 0; vector<struct lineEquation> le;
// 多边形的每条边
for (int j = 0; j < numLE; j++) {
// 求交点，将相交的直线暂存 x y(max) 1/k next
//该直线斜率不存在时，直线上的x都相等
if (lineEV[j].fk) {
x = lineEV[j].x1;
if (i - lineEV[j].y1 >= 0 && i - lineEV[j].y2 <= 0) {
tmpAE = new ActiveEdge();
tmpAE->x = x;
tmpAE->ymax = lineEV[j].y2;
lineAE.push_back(*tmpAE);
}
continue;
}
if (lineEV[j].k == 0) {
continue;
}
else {//斜率存在，求得交点
if (lineEV[j].y1 == i) {
if (lineEV[j].k > 0) {
x = lineEV[j].x1;
}
else {
x = lineEV[j].x2;
}
}
else if (lineEV[j].y2 == i) {
if (lineEV[j].k > 0) {
x = lineEV[j].x2;
}
else {
x = lineEV[j].x1;
}
}
else {
x = ((i - lineEV[j].b) / lineEV[j].k);
}
}
if (x - lineEV[j].x1 >=0 && x - lineEV[j].x2<=0) {
tmpAE = new ActiveEdge();
tmpAE->x = x;
tmpAE->ymax = lineEV[j].y2;
if(!lineEV[j].fk)
tmpAE->dx = 1 / lineEV[j].k;
lineAE.push_back(*tmpAE);
}
}

// 有效线段排序
sort(lineAE.begin(), lineAE.end(), cmp);
int  aeNum = lineAE.size();
if (aeNum > 0) {
// 转化为AE表
ActiveEdge *preAe = new ActiveEdge(), *head = new ActiveEdge();
preAe->x = lineAE[0].x;
preAe->ymax = lineAE[0].ymax;
preAe->dx = lineAE[0].dx;
preAe->next = NULL;
for (int k = 1; k < aeNum; k++) {
ActiveEdge *aeTmp = new ActiveEdge();
aeTmp->x = lineAE[k].x;
aeTmp->ymax = lineAE[k].ymax;
aeTmp->dx = lineAE[k].dx;
aeTmp->next = NULL;
preAe->next = aeTmp;
preAe = aeTmp;
}
}
}

int numAE = activeEdge.size();
// 使用AE表
// 对每个桶的每条有效边交点进行必配
struct MPOINT *a = NULL;// (tmpAE->x, ymin + i);
struct MPOINT *b = NULL;// (tmpAE->next->x, ymin + i);
tmpAE = new ActiveEdge();
preAE = new LineAE();
vector<double> po(1,0);
for (int i = 0; i < numAE; i++) {
int y = ymin + i;
bool f = true;// 单复数标志 匹配时使用

// 有效边链表 配对
*tmpAE = activeEdge[i];
*preAE = activeEdge[i];
a = NULL;
b = NULL;
po.clear();
while (tmpAE != NULL) {
po.push_back(tmpAE->x);
if (tmpAE->next !=NULL) {
if (tmpAE->x == tmpAE->next->x) {
if ((tmpAE->ymax > y && tmpAE->next->ymax > y)) {
po.push_back(tmpAE->x);
}
else if ((tmpAE->ymax < y && tmpAE->next->ymax < y)) {
po.pop_back();
}
else if ((tmpAE->ymax == y && tmpAE->next->ymax == y)) {
po.pop_back();
}
else {

}
if (tmpAE->next->next == NULL) {
break;
}
else {
tmpAE = tmpAE->next->next;
}
}
else {
tmpAE = tmpAE->next;
}
}
else {
break;
}
}
int con = po.size();
for (int k = 1; k < con; k+=2) {
a = new struct MPOINT(po[k-1], y);
b = new struct MPOINT(po[k], y);
Line_DDA(a, b);
}
}
}

// 获得福字矩阵
Matrix getFuMatrix(string filePath)
{
vector<struct MPOINT> pointV;
struct MPOINT a;
ifstream fin(filePath);
if (!fin.is_open()) {
}
while (!fin.eof())
{
fin >> a.x >> a.y;
a.x *= 300;
a.y *= 300;
a.y = 350 - a.y;
pointV.push_back(a);
}
int numPoint = pointV.size();
//生成点集矩阵
Matrix matrix(numPoint, 3);
for (int i = 0; i < numPoint; i++) {
matrix[i][0] = pointV[i].x;
matrix[i][1] = pointV[i].y;
matrix[i][2] = 1;
}
return matrix;
}

// 计算一阶矩二阶矩
//参数： 点云矩阵，质心，长半轴，短半轴，倾角（单位为角度不是弧度）
void computeSecondMoment(Matrix& matrix, struct MPOINT& center,GLdouble& w,GLdouble& l,GLdouble& theta)
{
int pointNum = matrix.rows();
center.x = 0.0;
center.y = 0.0;
for (int i = 0; i < pointNum; i++) {
center.x += matrix[i][0];
center.y += matrix[i][1];
}
// 质心
center.x /= pointNum;
center.y /= pointNum;

// 二阶矩矩阵 -- 半长轴 半短轴 角度（弧度）
double u20 = 0.0, u11 = 0.0, u02 = 0.0;
for (int i = 0; i < pointNum; i++) {
u20 += pow(matrix[i][0] - center.x, 2);
u11 += (matrix[i][0] - center.x) * (matrix[i][1] - center.y);
u02 += pow(matrix[i][1] - center.y, 2);
}
double lam1 = 0.5*((u20 + u02) + sqrt(pow(u20 - u02, 2) + 4 * u11*u11));
double lam2 = 0.5*((u20 + u02) - sqrt(pow(u20 - u02, 2) + 4 * u11*u11));
w = sqrt(lam1 / pointNum);//半长轴
l = sqrt(lam2 / pointNum);//半短轴
theta = 0.5*atan(2 * u11 / (u20 - u02)) * 180 / PI; // 椭圆倾角 这里化弧度为角度
}

//画福字 指定颜色，点的大小
void drawFu(Matrix& matrix,GLdouble pointSize,struct Color color)
{
struct MPOINT tmpP(0,0);
int r = matrix.rows();
for (int i = 0; i < r; i++) {
tmpP.x = matrix[i][0];
tmpP.y = matrix[i][1];
drawPoint(tmpP, pointSize, color);
}
}

//画福字的椭圆； 传入theta为弧度
void drawFuOval(struct Color color,struct MPOINT& center, double& w, double& l, double& theta)
{
longAxes = w;
shortAxes = l;
ovalAngle = theta;
// 画椭圆
Oval_Bresenham(&center, 1, color);

// 长轴、短轴线
struct MPOINT tmp(0, 0), tmp1(0, 0);
double cha1 = 100, cha2 = 50;
double k = tan(theta*PI / 180);
tmp.x = center.x + cha1;
tmp.y = center.y + cha1 * k;
tmp1.x = center.x - cha1;
tmp1.y = center.y - cha1 * k;
Line_DDA(&tmp, &tmp1);

k = tan((theta + 90)*PI / 180); // 化为角度计算
tmp.x = center.x + cha2;
tmp.y = center.y + cha2 * k;
tmp1.x = center.x - cha2;
tmp1.y = center.y - cha2 * k;
Line_DDA(&tmp, &tmp1);

}

// 平移矩阵
void matrixTransolation(Matrix& matrixT,GLdouble x, GLdouble y)
{
matrixT[0][0] = 1;
matrixT[0][1] = 0;
matrixT[0][2] = 0;
matrixT[1][0] = 0;
matrixT[1][1] = 1;
matrixT[1][2] = 0;
matrixT[2][0] = x;
matrixT[2][1] = y;
matrixT[2][2] = 1;
}
// 旋转矩阵
void matrixRotate(Matrix& matrixT, GLdouble x1, GLdouble x2,GLdouble y1,GLdouble y2)
{
matrixT[0][0] = x1;
matrixT[0][1] = x2;
matrixT[0][2] = 0;
matrixT[1][0] = y1;
matrixT[1][1] = y2;
matrixT[1][2] = 0;
matrixT[2][0] = 0;
matrixT[2][1] = 0;
matrixT[2][2] = 1;
}

void clear()
{
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}

// 福字变换
void fuTransformation()
{
double wX, lX, thetaX, wY, lY, thetaY;
struct MPOINT centerX, centerY;
struct Color color1(0, 0, 1);
Matrix matrixX = getFuMatrix("./X.txt"); // 待变换福
computeSecondMoment(matrixX, centerX, wX, lX, thetaX);
GLdouble w = wX, l = lX;

drawPoint(centerX, 5, color1);
drawFu(matrixX, 2, color1);
drawFuOval(color1, centerX, wX, lX, thetaX);

struct Color color(1, 0, 0);
Matrix matrixY = getFuMatrix("./Y.txt"); // 标准福
computeSecondMoment(matrixY, centerY, wY, lY, thetaY);
drawPoint(centerY, 5, color);
drawFu(matrixY, 2, color);
drawFuOval(color, centerY, wY, lY, thetaY);

Sleep(500);//-----------------------------------移位
clear();

drawPoint(centerY, 5, color);
drawFu(matrixY, 2, color);
drawFuOval(color, centerY, wY, lY, thetaY);
//移位，质心一致
Matrix matrixT(3, 3);
matrixTransolation(matrixT, centerY.x - centerX.x, centerY.y - centerX.y);
matrixX = matrixX * matrixT;
computeSecondMoment(matrixX, centerX, wX, lX, thetaX);
drawPoint(centerX, 5, color1);
drawFu(matrixX, 2, color1);
drawFuOval(color1, centerX, wX, lX, thetaX);

Sleep(500);//-----------------------------------缩放
clear();

drawPoint(centerY, 5, color);
drawFu(matrixY, 2, color);
drawFuOval(color, centerY, wY, lY, thetaY);
//缩放
//移至原点
matrixTransolation(matrixT, -centerX.x, -centerX.y);
matrixX = matrixX * matrixT;
//缩放
matrixRotate(matrixT, wY / wX, 0, 0, lY / lX);
matrixX = matrixX * matrixT;
//移回
matrixTransolation(matrixT, centerX.x, centerX.y);
matrixX = matrixX * matrixT;
computeSecondMoment(matrixX, centerX, wX, lX, thetaX);

drawPoint(centerX, 5, color1);
drawFu(matrixX, 2, color1);
drawFuOval(color1, centerX, wX, lX, thetaX);

Sleep(500);//-----------------------------------旋转
clear();

drawPoint(centerY, 5, color);
drawFu(matrixY, 2, color);
drawFuOval(color, centerY, wY, lY, thetaY);

GLdouble thetaXDegree = (thetaY - thetaX) * PI / 180;
//旋转
//移至原点
matrixTransolation(matrixT, -centerX.x, -centerX.y);
matrixX = matrixX * matrixT;
//旋转
matrixRotate(matrixT, cos(thetaXDegree), sin(thetaXDegree), -sin(thetaXDegree), cos(thetaXDegree));
matrixX = matrixX * matrixT;
//移回
matrixTransolation(matrixT, centerX.x, centerX.y);
matrixX = matrixX * matrixT;
computeSecondMoment(matrixX, centerX, wX, lX, thetaX);

drawPoint(centerX, 5, color1);
drawFu(matrixX, 2, color1);
drawFuOval(color1, centerX, wX, lX, thetaX);

}

// ---------------------------------------------------------------------------------------------------Bezier 曲线
GLdouble* Coefficient(int n)
{
GLdouble* res = new GLdouble[n + 1],tmp1,tmp2;
int con = 0,tmpI,mid = n/2;
res[0] = 1;
res[n] = 1;
for (int i = 1; i <= mid; i++) {
tmp1 = n;
tmpI = n;
con = i - 1;
while (con > 0) {
tmpI--;
tmp1 *= tmpI;
con--;
}
con = i - 1;
tmp2 = i;
while (con > 1) {
tmp2 *= con;
con--;
}
cout << tmp1 << " ********* " << tmp2 << endl;
res[i] = tmp1 / tmp2;
res[n - i] = res[i];
}
return res;
}
void bezier()
{
clear();
int pointNum = vertexSet.size();
struct  Color color(1,0,0);
drawPoint(vertexSet[0], 1.0, color);
for (int i = 1; i < pointNum; i++) {
drawPoint(vertexSet[i],1.0,color);
Line_DDA(&vertexSet[i-1], &vertexSet[i]);
}
struct  Color color1(0, 0, 1);
GLdouble deltaT = 0.01;
struct MPOINT *pointTmp = new MPOINT(),*perPoint = NULL;
if (pointNum == 2) {
for (GLdouble t = 0; t <= 1.0; t += deltaT) {
pointTmp->x = (1 - t) * vertexSet[0].x + t * vertexSet[1].x;
pointTmp->y = (1 - t) * vertexSet[0].y + t * vertexSet[1].y;
if (!perPoint) {
perPoint = new MPOINT();
*perPoint = *pointTmp;
drawPoint(*pointTmp, 1.0, color1);
}
else {
Line_DDA(perPoint, pointTmp);
*perPoint = *pointTmp;
}
}
}
else if (pointNum == 3) {
for (GLdouble t = 0; t <= 1.0; t += deltaT) {
pointTmp->x = (1 - t) *(1 - t)* vertexSet[0].x +2* t * (1 - t)* vertexSet[1].x + t * t * vertexSet[2].x;
pointTmp->y = (1 - t) *(1 - t)* vertexSet[0].y +2* t * (1 - t) *vertexSet[1].y + t * t * vertexSet[2].y;
if (!perPoint) {
perPoint = new MPOINT();
*perPoint = *pointTmp;
drawPoint(*pointTmp, 1.0, color1);
}
else {
Line_DDA(perPoint, pointTmp);
*perPoint = *pointTmp;
}
}
}
else {

/*
// 3次bezier分段
int i = 3;
for (; i < pointNum; i+=3) {
for (GLdouble t = 0; t <= 1.0; t += deltaT) {
pointTmp.x = (1 - t) *(1 - t)* (1 - t) * vertexSet[i - 3].x + 3 * t * (1 - t)*(1 - t)* vertexSet[i - 2].x + 3 * t * t *(1 - t)* vertexSet[i - 1].x + t * t*t*vertexSet[i].x;
pointTmp.y = (1 - t) *(1 - t)* (1 - t) * vertexSet[i - 3].y + 3 * t * (1 - t)*(1 - t)* vertexSet[i - 2].y + 3 * t * t *(1 - t)* vertexSet[i - 1].y + t * t*t*vertexSet[i].y;
drawPoint(pointTmp, 1.0, color1);
}
}*/
GLdouble* coefficient = Coefficient(pointNum - 1);
for (GLdouble t = 0; t <= 1.0; t += deltaT) {
pointTmp->x = 0;
pointTmp->y = 0;
for (int i = 0; i < pointNum; i++) {
pointTmp->x += coefficient[i] * pow(1 - t, pointNum - 1 - i)*pow(t, i)*vertexSet[i].x;
pointTmp->y += coefficient[i] * pow(1 - t, pointNum - 1 - i)*pow(t, i)*vertexSet[i].y;
}
if (!perPoint) {
perPoint = new MPOINT();
*perPoint = *pointTmp;
drawPoint(*pointTmp, 1.0, color1);
}
else {
Line_DDA(perPoint,pointTmp);
*perPoint = *pointTmp;
}
}
}
}

//==========================================================================事件========

/*鼠标点击事件 */
void mouseClick(int btn, int state, int x, int y)
{
if (choice == 6 && btn == 0 && state == 0) {
struct MPOINT* tmpPoint = new MPOINT(x,y);
vertexSet.push_back(*tmpPoint);
bool f = false;
if (vertexSet.size()>1&&*tmpPoint == vertexSet[0]) {
f = true;
tmpPoint->x = vertexSet[0].x;
tmpPoint->y = vertexSet[0].y;
}
struct Color color(1, 0, 0);
drawPoint(*tmpPoint,1.0,color);
if (f) {
vertexSet.pop_back();//弹出最后一个顶点，与开始点重合
double ymin, ymax;
buildPloy(vertexSet,ymin,ymax);
cout <<"最小扫描线: "<< ymin << "\t最大扫描线: " << ymax << endl;
buildAE(ymin,ymax);
}
}
if (choice == 8 && btn == 0 && state == 0) {
struct MPOINT* tmpPoint = new MPOINT(x, y);
vertexSet.push_back(*tmpPoint);
if (vertexSet.size() >= 2) {
bezier();
}
}
if (btn == 0 && state == 0) {
if (oldPoint == NULL) {
oldPoint = new MPOINT(x, y);
}
else {
curPoint = new MPOINT(x, y);
}
}
if (oldPoint != NULL && curPoint != NULL) {
if (choice == 1) {
Line_DDA(oldPoint, curPoint); // DDA for line
//Line_Bresenham(oldPoint, curPoint);// Bresenham for Line
}
else if (choice == 2) {
GLdouble R = sqrt(pow(curPoint->x - oldPoint->x, 2) + pow(curPoint->y - oldPoint->y, 2));
//Circle_DDA(oldPoint, R); // DDA for Circle
//Circle_Polar(oldPoint,R); // Polar for Circle
Circle_Bresenham(oldPoint, R); // Bresenham for Circle
}
else if (choice == 3) {
struct Color color(1, 0, 0);
Oval_Bresenham(oldPoint,1,color); // Bresenham for Oval
}
flag = 0;
free(oldPoint);
free(curPoint);
oldPoint = NULL;
curPoint = NULL;
}
}

//键盘事件
void SpecialKey(GLint c, GLint x, GLint y) {
//向上的箭头，清除窗口
if (c == GLUT_KEY_UP) {
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
//向下的箭头，输入椭圆参数
if (c == GLUT_KEY_DOWN) {
cout << "Please input the  long axis, shaort axis and the rotation angle of Oval\n";
cin >> longAxes >> shortAxes >> ovalAngle;
}
if (c == GLUT_KEY_LEFT) {

}
//ESC 退出窗口
if (c == 27) {
exit(0);
}
}

/* 鼠标移动事件 */
void mouseMove(int x, int y)
{
//printf("移动鼠标中，x:%d,y%d\n", x, y);
}

// 菜单选择后

if (value == 1) {
choice = 1;
}
if (value == 2) {
choice = 2;
}
if (value == 3) {
choice = 3;
}
if (value == 6) {
choice = 6;
vertexSet.clear();
}
if (value == 7) {
choice = 7;
fuTransformation();
}
if (value == 8) {
choice = 8;
vertexSet.clear();
}
if (value == 4) {
vertexSet.clear();
activeEdge.clear();
lineEV.clear();
system("cls");
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}
if (value == 5) {
exit(0);
}
free(oldPoint);
free(curPoint);
oldPoint = NULL;
curPoint = NULL;
}

// 初始化菜单项
{
//添加菜单项
choice = 1;
}

//============================================== MAIN =============================
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
/*显示模式*/
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
/*创建窗口*/
glutInitWindowPosition(100, 100);
glutInitWindowSize(600, 600);
glutCreateWindow("OpenGL");
glClearColor(1.0, 1.0, 0.6, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0f, 0.0f, 0.0f);
/*窗口坐标设置*/
gluOrtho2D(0, 600.0, 600.0, 0);
/*回调函数*/
glutDisplayFunc(display);
/*鼠标点击事件，鼠标点击或者松开时调用 */
glutMouseFunc(mouseClick);
/*鼠标移动事件，鼠标按下并移动时调用 */
glutMotionFunc(mouseMove);
/*键盘事件，键盘按下时调用 */
glutSpecialFunc(&SpecialKey);
/*菜单*/
}