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; head = preAe; 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; } activeEdge.push_back(*head); } } 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()) { std::cerr << "file read wrong!\n"; } 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(¢er, 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); } // 菜单选择后 void mymenu(int value) { 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; } // 初始化菜单项 void initMenu() { //添加菜单项 glutAddMenuEntry("Line", 1); glutAddMenuEntry("Circle", 2); glutAddMenuEntry("Oval", 3); glutAddMenuEntry("Polygonal scan conversion", 6); glutAddMenuEntry("FU transformation", 7); glutAddMenuEntry("Bezier", 8); glutAddMenuEntry("Clear Screen", 4); glutAddMenuEntry("Exit", 5); glutAttachMenu(GLUT_RIGHT_BUTTON);//把当前菜单注册到指定的鼠标键 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); /*菜单*/ int menu=glutCreateMenu(mymenu);//注册菜单回调函数 //添加菜单项 initMenu(); /*主循环*/ glutMainLoop(); return 0; }