其他计算机图形学实验见 链接
#include<gl/glut.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const float window_width = 800, window_height = 600;
const int d = 8;
struct point
{
float x, y;
point() {}
point(float xx, float yy)
:x(xx), y(yy) {}
};
vector<point> input_vertice;
vector<point> controlpoint;
char OP;
float controlpoint_color[3] = { 1,0,0 };
float straightline_color[3] = { 0,1,0 };
float bezierline_color[3] = { 0,0,1 };
void draw_a_point(float x, float y, float color[]);
void deCasteljau();
void mymouse(int button, int state, int x, int y);
void dragmouse(int x, int y);
void keyboard(unsigned char key, int x, int y);
int getdis(int x, int y);
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(50, 50);
glutInitWindowSize(window_width, window_height);
glutCreateWindow("de Casteljau 绘制bezier曲线");
cout << "键盘点击p后,点击左键绘制控制点" << endl;
cout << "键盘点击i后,插入控制点" << endl;
cout << "键盘点击d后,移动控制点" << endl;
cout << "键盘点击e后,点击鼠标左键删除控制点" << endl;
cout << "按ESC退出" << endl << endl;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, window_width, 0, window_height);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glutMouseFunc(&mymouse);
glutMotionFunc(&dragmouse);
glutKeyboardFunc(&keyboard);
glutMainLoop();
return 0;
}
void draw_a_point(float x, float y, float color[])
{
glPointSize(3.0f);
glBegin(GL_POINTS);
glColor3fv(color);
glVertex2f(x, y);
glEnd();
glFlush();
}
int getdis(int x, int y)
{
int ans = -1;
float shortdis = 99999999;
for (int i = 0; i < input_vertice.size(); i++)
{
float dis = sqrt(pow(x - input_vertice[i].x, 2) + pow(y - input_vertice[i].y, 2));
if (dis < shortdis && dis <= d)
{
shortdis = dis;
ans = i;
}
}
return ans;
}
int index1 = -1;
void mymouse(int button, int state, int x, int y)
{
if (OP == 'p')
{
int drag_point_index = -1;
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
int index = getdis(x, window_height - y);
if (index == -1)
{
draw_a_point(x, window_height - y, controlpoint_color);
point p(x, window_height - y);
input_vertice.push_back(p);
cout << "新输入的控制点" << input_vertice.size() << ":(" << x << ", " << window_height - y << ")" << endl;
}
controlpoint = input_vertice;
if (input_vertice.size() >= 2)
deCasteljau();
else
{
glBegin(GL_LINE_STRIP);
glColor3fv(straightline_color);
for (int i = 0; i < input_vertice.size(); i++)
glVertex2f(input_vertice[i].x, input_vertice[i].y);
glEnd();
glFlush();
}
}
}
if (OP == 'i')
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
index1 = getdis(x, window_height - y);
cout << "将插入新的控制点到 选中的控制点" << index1 << "前" << endl;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP && index1 != -1)
{
input_vertice.insert(input_vertice.begin() + index1, point(x, window_height - y));
}
controlpoint = input_vertice;
if (input_vertice.size() >= 2)
deCasteljau();
else
{
glBegin(GL_LINE_STRIP);
glColor3fv(straightline_color);
for (int i = 0; i < input_vertice.size(); i++)
glVertex2f(input_vertice[i].x, input_vertice[i].y);
glEnd();
glFlush();
}
}
if (OP == 'e')
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
int index = getdis(x, window_height - y);
cout << "删除点" << index << endl;
if (index != -1)
{
vector<point>::iterator it = input_vertice.begin();
cout << (*(it + index)).x << " " << (*(it + index)).y << endl;
input_vertice.erase(it + index);
}
else
cout << "没有可以删除的点" << endl;
glClear(GL_COLOR_BUFFER_BIT);
controlpoint = input_vertice;
deCasteljau();
}
}
}
void dragmouse(int x, int y)
{
int index = getdis(x, window_height - y);
if (OP == 'd' && index != -1)
{
cout << "修改控制点" << input_vertice.size() << ":(" << input_vertice[index].x << ", " << input_vertice[index].y << ")" << endl;
input_vertice[index].x = x;
input_vertice[index].y = window_height - y;
controlpoint = input_vertice;
if (input_vertice.size() >= 2)
deCasteljau();
else
{
glBegin(GL_LINE_STRIP);
glColor3fv(straightline_color);
for (int i = 0; i < input_vertice.size(); i++)
glVertex2f(input_vertice[i].x, input_vertice[i].y);
glEnd();
glFlush();
}
}
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 27)
exit(0);
if (key == 'p')
{
OP = 'p';
cout << "请点击鼠标左键,开始绘制控制点以及bezier曲线" << endl;
}
if (key == 'd')
{
OP = 'd';
cout << "请按住端点拖动" << endl;
}
if (key == 'i')
{
OP = 'i';
cout << "请点击一个已有的控制点按住不放,松开位置为新插入顶点的位置。新插入的顶点位于点击的顶点之前。 "<< endl;
}
if (key == 'e')
{
OP = 'e';
cout << "鼠标左键点击要删除的点" << endl;
}
}
void deCasteljau()
{
vector<point> bezierpoint;
int n = controlpoint.size();
for (double t = 0.0; t <= 1.0; t += 0.005 / n)
{
for (int i = 1; i < n; i++)
{
for (int j = 0; j < n - i; j++)
{
if (i == 1)
{
controlpoint[j].x = (1 - t) * input_vertice[j].x + t * input_vertice[j + 1].x;
controlpoint[j].y = (1 - t) * input_vertice[j].y + t * input_vertice[j + 1].y;
continue;
}
else
{
controlpoint[j].x = (1 - t) * controlpoint[j].x + t * controlpoint[j + 1].x;
controlpoint[j].y = (1 - t) * controlpoint[j].y + t * controlpoint[j + 1].y;
}
}
}
bezierpoint.push_back(controlpoint[0]);
}
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINE_STRIP);
glColor3fv(straightline_color);
for (int i = 0; i < input_vertice.size(); i++)
glVertex2f(input_vertice[i].x, input_vertice[i].y);
glEnd();
glFlush();
glLineWidth(3.0f);
glBegin(GL_LINE_STRIP);
glColor3fv(bezierline_color);
for (int i = 0; i < bezierpoint.size(); i++)
glVertex2f(bezierpoint[i].x, bezierpoint[i].y);
glEnd();
glFlush();
}