#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<=)) && (abs(this->y - a.y)<=);
}
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 = ,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 = ; i < ; i++) {
glVertex2f(i, *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 = ; 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=;
GLdouble k = (dy) / (GLdouble)dx;
glBegin(GL_POINTS);
{
glVertex2i(round(x), round(y));
if (k >= ) {
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 *= -;
dy *= -;
}
if (k <= )
{
e = -dx;
while (x != p2->x && y != p2->y) {
e += * dy;
if (e > ) {
if (x < p2->x || y< p2->y) {
x++;
y++;
}
else if (x > p2->x || y > p2->y)
{
x--;
y--;
}
e -= * dx;
}
else {
if (x < p2->x) {
x++;
}
else if(x > p2->x)
{
x--;
}
}
glVertex2i(round(x), round(y));
}
}
else if (k > ) {
e = -dy;
while (x != p2->x && y != p2->y) {
e += * dx;
if (e > ) {
if (x < p2->x || y< p2->y) {
x++;
y++;
}
else if (x > p2->x || y > p2->y)
{
x--;
y--;
}
e -= * dy;
}
else {
if (y < p2->y) {
y++;
}
else if (y > p2->y)
{
y--;
}
}
glVertex2i(round(x), round(y));
}
}
}
else {
if (k >= -)
{
e = -dx;
while (x != p2->x && y != p2->y) {
e += abs(dy)*;
if (e > ) {
if (x > p2->x || y< p2->y) {
x--;
y++;
}
else if (x < p2->x || y > p2->y)
{
x++;
y--;
}
e -= abs(dx)*;
}
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 += * abs(dx);
if (e > ) {
if (x > p2->x || y< p2->y) {
x--;
y++;
}
else if (x < p2->x || y > p2->y)
{
x++;
y--;
}
e -= * 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 = ;
GLdouble x=c->x, y=c->y;
glBegin(GL_POINTS);
{
for (int i = ; i < n; i++)
{
x =c->x + R * cos( * PI *i/ n);
y =c->y + R * sin( * 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 = - R, x = , y = R;
while (x <= y)
{
Draw8(c, x ,y);
if (d <= )
{
d += * x + ;
x++;
}
else
{
d += * (x-y) + ;
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 = , e = / R;
glBegin(GL_POINTS);
{
while (theta < * 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 / ) - (Y - c->y)*sin(ovalAngle*PI / ) + c->x;
y = (X - c->x)*sin(ovalAngle*PI / ) + (Y - c->y)*cos(ovalAngle*PI / ) + 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 <= || shortAxes <= ) {
longAxes = , shortAxes = ;
}
GLdouble d = shortAxes * shortAxes + longAxes * longAxes*(0.25 - shortAxes), x = , y = shortAxes;
while (shortAxes*shortAxes*(x + ) < longAxes * longAxes * (y - 0.5))
{
Draw4(c,x, y, pointSize,color);
if (d <= )
{
d += shortAxes * shortAxes *( * x + );
x++;
}
else
{
d += shortAxes * shortAxes *( * x + ) + longAxes * longAxes *(- * y + );
x++;
y--;
}
} d = shortAxes * shortAxes*(x + 0.5)*(x + 0.5) + longAxes * longAxes *(y - )*(y - ) - longAxes * longAxes * shortAxes * shortAxes;
while (y >= )
{
Draw4(c,x,y, pointSize,color);
if (d <= )
{
d += shortAxes * shortAxes *(*x + ) + longAxes * longAxes *(-*y + );
x++;
y--;
}
else
{
d += longAxes * longAxes *(-*y + ),
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[].y;
ymax = ymin;
//划线二
for (int i = ; i < len; i++) {
//划线
Line_DDA(&vertexSet[i - ], &vertexSet[i]);
// k不存在时 x = x1 = x2
if (abs((vertexSet[i - ].x - vertexSet[i].x)) <1e- ) {
tmpE.fk = true;
}
else { // y = k*x +b
tmpE.fk = false;
tmpE.k = (double)(vertexSet[i - ].y - vertexSet[i].y) / (double)(vertexSet[i - ].x - vertexSet[i].x);
tmpE.b = vertexSet[i - ].y - tmpE.k * vertexSet[i - ].x;
// k == 0 时 y = b
}
// 求直线所占范围 xmin xmax ymin ymax
if (vertexSet[i - ].x <= vertexSet[i].x) {
tmpE.x1 = vertexSet[i - ].x;
tmpE.x2 = vertexSet[i].x;
}
else {
tmpE.x1 = vertexSet[i].x;
tmpE.x2 = vertexSet[i - ].x;
}
if (vertexSet[i - ].y <= vertexSet[i].y) {
tmpE.y1 = vertexSet[i - ].y;
tmpE.y2 = vertexSet[i].y;
}
else {
tmpE.y1 = vertexSet[i].y;
tmpE.y2 = vertexSet[i - ].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[], &vertexSet[len-]);
// k不存在时 x = x1 = x2
if (abs((vertexSet[].x - vertexSet[len -].x)) < 1e-) {
tmpE.fk = true;
}
else {
tmpE.fk = false;
tmpE.k = (double)(vertexSet[].y - vertexSet[len - ].y) / (double)(vertexSet[].x - vertexSet[len - ].x);
tmpE.b = vertexSet[].y - tmpE.k * vertexSet[].x;
}
if (vertexSet[].x <= vertexSet[len - ].x) {
tmpE.x1 = vertexSet[].x;
tmpE.x2 = vertexSet[len - ].x;
}
else {
tmpE.x1 = vertexSet[len - ].x;
tmpE.x2 = vertexSet[].x;
}
if (vertexSet[].y >= vertexSet[len -].y) {
tmpE.y1 = vertexSet[len - ].y;
tmpE.y2 = vertexSet[].y;
}
else {
tmpE.y1 = vertexSet[].y;
tmpE.y2 = vertexSet[len - ].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 = ; vector<struct lineEquation> le;
// 多边形的每条边
for (int j = ; j < numLE; j++) {
// 求交点,将相交的直线暂存 x y(max) 1/k next
//该直线斜率不存在时,直线上的x都相等
if (lineEV[j].fk) {
x = lineEV[j].x1;
if (i - lineEV[j].y1 >= && i - lineEV[j].y2 <= ) {
tmpAE = new ActiveEdge();
tmpAE->x = x;
tmpAE->ymax = lineEV[j].y2;
lineAE.push_back(*tmpAE);
}
continue;
}
if (lineEV[j].k == ) {
continue;
}
else {//斜率存在,求得交点
if (lineEV[j].y1 == i) {
if (lineEV[j].k > ) {
x = lineEV[j].x1;
}
else {
x = lineEV[j].x2;
}
}
else if (lineEV[j].y2 == i) {
if (lineEV[j].k > ) {
x = lineEV[j].x2;
}
else {
x = lineEV[j].x1;
}
}
else {
x = ((i - lineEV[j].b) / lineEV[j].k);
}
}
if (x - lineEV[j].x1 >= && x - lineEV[j].x2<=) {
tmpAE = new ActiveEdge();
tmpAE->x = x;
tmpAE->ymax = lineEV[j].y2;
if(!lineEV[j].fk)
tmpAE->dx = / lineEV[j].k;
lineAE.push_back(*tmpAE);
}
} // 有效线段排序
sort(lineAE.begin(), lineAE.end(), cmp);
int aeNum = lineAE.size();
if (aeNum > ) {
// 转化为AE表
ActiveEdge *preAe = new ActiveEdge(), *head = new ActiveEdge();
preAe->x = lineAE[].x;
preAe->ymax = lineAE[].ymax;
preAe->dx = lineAE[].dx;
preAe->next = NULL;
head = preAe;
for (int k = ; 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(,);
for (int i = ; 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 = ; k < con; k+=) {
a = new struct MPOINT(po[k-], 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 *= ;
a.y *= ;
a.y = - a.y;
pointV.push_back(a);
}
int numPoint = pointV.size();
//生成点集矩阵
Matrix matrix(numPoint, );
for (int i = ; i < numPoint; i++) {
matrix[i][] = pointV[i].x;
matrix[i][] = pointV[i].y;
matrix[i][] = ;
}
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 = ; i < pointNum; i++) {
center.x += matrix[i][];
center.y += matrix[i][];
}
// 质心
center.x /= pointNum;
center.y /= pointNum; // 二阶矩矩阵 -- 半长轴 半短轴 角度(弧度)
double u20 = 0.0, u11 = 0.0, u02 = 0.0;
for (int i = ; i < pointNum; i++) {
u20 += pow(matrix[i][] - center.x, );
u11 += (matrix[i][] - center.x) * (matrix[i][] - center.y);
u02 += pow(matrix[i][] - center.y, );
}
double lam1 = 0.5*((u20 + u02) + sqrt(pow(u20 - u02, ) + * u11*u11));
double lam2 = 0.5*((u20 + u02) - sqrt(pow(u20 - u02, ) + * u11*u11));
w = sqrt(lam1 / pointNum);//半长轴
l = sqrt(lam2 / pointNum);//半短轴
theta = 0.5*atan( * u11 / (u20 - u02)) * / PI; // 椭圆倾角 这里化弧度为角度
} //画福字 指定颜色,点的大小
void drawFu(Matrix& matrix,GLdouble pointSize,struct Color color)
{
struct MPOINT tmpP(,);
int r = matrix.rows();
for (int i = ; i < r; i++) {
tmpP.x = matrix[i][];
tmpP.y = matrix[i][];
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, , color); // 长轴、短轴线
struct MPOINT tmp(, ), tmp1(, );
double cha1 = , cha2 = ;
double k = tan(theta*PI / );
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 + )*PI / ); // 化为角度计算
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[][] = ;
matrixT[][] = ;
matrixT[][] = ;
matrixT[][] = ;
matrixT[][] = ;
matrixT[][] = ;
matrixT[][] = x;
matrixT[][] = y;
matrixT[][] = ;
}
// 旋转矩阵
void matrixRotate(Matrix& matrixT, GLdouble x1, GLdouble x2,GLdouble y1,GLdouble y2)
{
matrixT[][] = x1;
matrixT[][] = x2;
matrixT[][] = ;
matrixT[][] = y1;
matrixT[][] = y2;
matrixT[][] = ;
matrixT[][] = ;
matrixT[][] = ;
matrixT[][] = ;
} void clear()
{
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
} // 福字变换
void fuTransformation()
{
double wX, lX, thetaX, wY, lY, thetaY;
struct MPOINT centerX, centerY;
struct Color color1(, , );
Matrix matrixX = getFuMatrix("./X.txt"); // 待变换福
computeSecondMoment(matrixX, centerX, wX, lX, thetaX);
GLdouble w = wX, l = lX; drawPoint(centerX, , color1);
drawFu(matrixX, , color1);
drawFuOval(color1, centerX, wX, lX, thetaX); struct Color color(, , );
Matrix matrixY = getFuMatrix("./Y.txt"); // 标准福
computeSecondMoment(matrixY, centerY, wY, lY, thetaY);
drawPoint(centerY, , color);
drawFu(matrixY, , color);
drawFuOval(color, centerY, wY, lY, thetaY); Sleep();//-----------------------------------移位
clear(); drawPoint(centerY, , color);
drawFu(matrixY, , color);
drawFuOval(color, centerY, wY, lY, thetaY);
//移位,质心一致
Matrix matrixT(, );
matrixTransolation(matrixT, centerY.x - centerX.x, centerY.y - centerX.y);
matrixX = matrixX * matrixT;
computeSecondMoment(matrixX, centerX, wX, lX, thetaX);
drawPoint(centerX, , color1);
drawFu(matrixX, , color1);
drawFuOval(color1, centerX, wX, lX, thetaX); Sleep();//-----------------------------------缩放
clear(); drawPoint(centerY, , color);
drawFu(matrixY, , color);
drawFuOval(color, centerY, wY, lY, thetaY);
//缩放
//移至原点
matrixTransolation(matrixT, -centerX.x, -centerX.y);
matrixX = matrixX * matrixT;
//缩放
matrixRotate(matrixT, wY / wX, , , lY / lX);
matrixX = matrixX * matrixT;
//移回
matrixTransolation(matrixT, centerX.x, centerX.y);
matrixX = matrixX * matrixT;
computeSecondMoment(matrixX, centerX, wX, lX, thetaX); drawPoint(centerX, , color1);
drawFu(matrixX, , color1);
drawFuOval(color1, centerX, wX, lX, thetaX); Sleep();//-----------------------------------旋转
clear(); drawPoint(centerY, , color);
drawFu(matrixY, , color);
drawFuOval(color, centerY, wY, lY, thetaY); GLdouble thetaXDegree = (thetaY - thetaX) * PI / ;
//旋转
//移至原点
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, , color1);
drawFu(matrixX, , color1);
drawFuOval(color1, centerX, wX, lX, thetaX); } // ---------------------------------------------------------------------------------------------------Bezier 曲线
GLdouble* Coefficient(int n)
{
GLdouble* res = new GLdouble[n + ],tmp1,tmp2;
int con = ,tmpI,mid = n/;
res[] = ;
res[n] = ;
for (int i = ; i <= mid; i++) {
tmp1 = n;
tmpI = n;
con = i - ;
while (con > ) {
tmpI--;
tmp1 *= tmpI;
con--;
}
con = i - ;
tmp2 = i;
while (con > ) {
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(,,);
drawPoint(vertexSet[], 1.0, color);
for (int i = ; i < pointNum; i++) {
drawPoint(vertexSet[i],1.0,color);
Line_DDA(&vertexSet[i-], &vertexSet[i]);
}
struct Color color1(, , );
GLdouble deltaT = 0.01;
struct MPOINT *pointTmp = new MPOINT(),*perPoint = NULL;
if (pointNum == ) {
for (GLdouble t = ; t <= 1.0; t += deltaT) {
pointTmp->x = ( - t) * vertexSet[].x + t * vertexSet[].x;
pointTmp->y = ( - t) * vertexSet[].y + t * vertexSet[].y;
if (!perPoint) {
perPoint = new MPOINT();
*perPoint = *pointTmp;
drawPoint(*pointTmp, 1.0, color1);
}
else {
Line_DDA(perPoint, pointTmp);
*perPoint = *pointTmp;
}
}
}
else if (pointNum == ) {
for (GLdouble t = ; t <= 1.0; t += deltaT) {
pointTmp->x = ( - t) *( - t)* vertexSet[].x +* t * ( - t)* vertexSet[].x + t * t * vertexSet[].x;
pointTmp->y = ( - t) *( - t)* vertexSet[].y +* t * ( - t) *vertexSet[].y + t * t * vertexSet[].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 - );
for (GLdouble t = ; t <= 1.0; t += deltaT) {
pointTmp->x = ;
pointTmp->y = ;
for (int i = ; i < pointNum; i++) {
pointTmp->x += coefficient[i] * pow( - t, pointNum - - i)*pow(t, i)*vertexSet[i].x;
pointTmp->y += coefficient[i] * pow( - t, pointNum - - 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 == && btn == && state == ) {
struct MPOINT* tmpPoint = new MPOINT(x,y);
vertexSet.push_back(*tmpPoint);
bool f = false;
if (vertexSet.size()>&&*tmpPoint == vertexSet[]) {
f = true;
tmpPoint->x = vertexSet[].x;
tmpPoint->y = vertexSet[].y;
}
struct Color color(, , );
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 == && btn == && state == ) {
struct MPOINT* tmpPoint = new MPOINT(x, y);
vertexSet.push_back(*tmpPoint);
if (vertexSet.size() >= ) {
bezier();
}
}
if (btn == && state == ) {
if (oldPoint == NULL) {
oldPoint = new MPOINT(x, y);
}
else {
curPoint = new MPOINT(x, y);
}
}
if (oldPoint != NULL && curPoint != NULL) {
if (choice == ) {
Line_DDA(oldPoint, curPoint); // DDA for line
//Line_Bresenham(oldPoint, curPoint);// Bresenham for Line
}
else if (choice == ) {
GLdouble R = sqrt(pow(curPoint->x - oldPoint->x, ) + pow(curPoint->y - oldPoint->y, ));
//Circle_DDA(oldPoint, R); // DDA for Circle
//Circle_Polar(oldPoint,R); // Polar for Circle
Circle_Bresenham(oldPoint, R); // Bresenham for Circle
}
else if (choice == ) {
struct Color color(, , );
Oval_Bresenham(oldPoint,,color); // Bresenham for Oval
}
flag = ;
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 == ) {
exit();
}
} /* 鼠标移动事件 */
void mouseMove(int x, int y)
{
//printf("移动鼠标中,x:%d,y%d\n", x, y);
} // 菜单选择后
void mymenu(int value) { if (value == ) {
choice = ;
}
if (value == ) {
choice = ;
}
if (value == ) {
choice = ;
}
if (value == ) {
choice = ;
vertexSet.clear();
}
if (value == ) {
choice = ;
fuTransformation();
}
if (value == ) {
choice = ;
vertexSet.clear();
}
if (value == ) {
vertexSet.clear();
activeEdge.clear();
lineEV.clear();
system("cls");
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}
if (value == ) {
exit();
}
free(oldPoint);
free(curPoint);
oldPoint = NULL;
curPoint = NULL;
} // 初始化菜单项
void initMenu()
{
//添加菜单项
glutAddMenuEntry("Line", );
glutAddMenuEntry("Circle", );
glutAddMenuEntry("Oval", );
glutAddMenuEntry("Polygonal scan conversion", );
glutAddMenuEntry("FU transformation", );
glutAddMenuEntry("Bezier", );
glutAddMenuEntry("Clear Screen", );
glutAddMenuEntry("Exit", );
glutAttachMenu(GLUT_RIGHT_BUTTON);//把当前菜单注册到指定的鼠标键
choice = ;
} //============================================== MAIN =============================
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
/*显示模式*/
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
/*创建窗口*/
glutInitWindowPosition(, );
glutInitWindowSize(, );
glutCreateWindow("OpenGL");
glClearColor(1.0, 1.0, 0.6, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0f, 0.0f, 0.0f);
/*窗口坐标设置*/
gluOrtho2D(, 600.0, 600.0, );
/*回调函数*/
glutDisplayFunc(display);
/*鼠标点击事件,鼠标点击或者松开时调用 */
glutMouseFunc(mouseClick);
/*鼠标移动事件,鼠标按下并移动时调用 */
glutMotionFunc(mouseMove);
/*键盘事件,键盘按下时调用 */
glutSpecialFunc(&SpecialKey);
/*菜单*/
int menu=glutCreateMenu(mymenu);//注册菜单回调函数
//添加菜单项
initMenu(); /*主循环*/
glutMainLoop();
return ;
}

openGL笔记-画基本图形的更多相关文章

  1. openGL实现二维图形和三维图形

    openGL是一个强大的底层图形库,其命令最初的时候使用C语言实现的.openGL定义了一个图形程序接口,常用于制作处理三维图像,功能强大,调用方便,在图像处理十分受欢迎. 实现图形主要使用的是ope ...

  2. OpenGL笔记(一) 绘制三角形

    GLTools: 一些有用且可复用的函数 GLEW: OpenGL API的一些扩展机制 GLUT: OpenGL Utility toolkit, OpenGL跨平台相关,隐藏平台相关细节 RC代表 ...

  3. Android OpenGL ES 画球体

    近期由于兴趣所向.開始学习OpenGL绘图. 本文以"画球体"为点,小结一下近期所学. > 初识OpenGL ES 接触OpenGL是从Android開始的.众所周知,And ...

  4. 使用OpenGL ES绘制3D图形

    如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出3D图形了. 使用OpenGL  ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的 ...

  5. 放肆的使用UIBezierPath和CAShapeLayer画各种图形

    CAShapeLayer 是 CALayer 的子类,但是比 CALayer 更灵活,可以画出各种图形,当然,你也可以使用其他方式来画,随你. 杂谈 在 CAShapeLayer 中,也可以像 CAL ...

  6. 使用UIBezierPath和CAShapeLayer画各种图形

    转载自:http://www.cocoachina.com/ios/20160214/15251.html CAShapeLayer 是 CALayer 的子类,但是比 CALayer 更灵活,可以画 ...

  7. iOS-CGContextRef画各种图形例子

    iOS-CGContextRef画各种图形例子 绘制效果图 绘制代码 - (void)drawRect:(CGRect)rect { //一个不透明类型的Quartz 2D绘画环境,相当于一个画布,你 ...

  8. opengl笔记——旋转,一段代码的理解

    重看:opengl笔记——OpenGL好资料备忘 在找到这段代码,对理解opengl旋转很有帮助 ... glPushMatrix(); // initialze ModelView matrix g ...

  9. Java界面编程-建立一个可以画出图形的简单框架

    引子:总共使用3个.java文件,建立一个简单界面编程的框架. 第1个文件:NotHelloWorldComponent.java //NotHelloWorldComponent.java 1 im ...

随机推荐

  1. PMS---团队展示

    点我查看作业原题 [队名] PMS(一群pm) [拟做的团队项目描述] 基于监控场景的视频摘要与人车检测跟踪系统 A system, under monitor scene, for video su ...

  2. 深入理解Java类加载器(2)

    1 基本信息 每个开发人员对Java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java的类加载机制是技术体系中比较核心的 ...

  3. 关于MUI v0.18.0版本 Table组件里的复选框不能选的解决方案

    前段时间在用MUI的时候,Table组件出现复选框不能选的bug(描述: 点击复选框,点击事件会触发,复选框勾选状态无变化). 解决方法: 用CheckBox组件代替Table组件自带的复选框. 解决 ...

  4. C# 正则提取字符串(提取一个或多个)

    实例一:string result = ""; string str = "大家好! <User EntryTime='2010-10-7' Email='zhan ...

  5. sed ,awk , cut三剑客的区别

    sed: sed只能截取文件中以行的来截取数据,,(grep命令可以过滤到某一行) 例如: [root@localhost ~]# sed  -n  '2,3p'  /etc/passwd       ...

  6. ISCC2018(misc)

    ISCC2018 misc writeup(部分) 这些天做个了iscc题目,有些题目不是很难,网上都有相同的题或者类似的题目,但是我很菜,没做出来多少. #misc1:Where is the FL ...

  7. 在linux中安装jdk以及tomcat并shell脚本关闭启动的进程

    在命令行模式中输入uname -a ,如下图,当界面展示i386就说明本linux系统为32版本,就在官网下载对应jdk版本,或者直接到我的网盘上下载http://pan.baidu.com/s/1c ...

  8. [转帖]脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

    脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?     http://www.52im.net/thread-1732-1-1.html   1.引言 本文接上篇<脑残式网 ...

  9. [转贴]systemd 编写服务管理脚本

    [转贴]sparkdev大神的博客, 关于 systemd的配置文件的 介绍, 自己之前二进制安装 k8s 时 超过一个 service文件 但是当时不明不白的. 现在再学习一下大神的文章 的确牛B ...

  10. SPOJ NETADMIN_Smart Network Administrator

    给一个图,某些点需要单独以某一种颜色的线连接到1点,问如何安排能够使得整个图颜色最多的一条路颜色最少. 显然,二分枚举然后加以颜色其实就是流量了,相当于对每条边限定一个当前二分的流量值,判断能否满流即 ...