实验八
曲线绘制
一、实验目的
1、掌握 Bezier 曲线的绘制;
2、掌握 B 样条曲线的绘制。
二、实验要求
1、通过菜单完成两种曲线的绘制:
1. Bezier 曲线(三次或四次)
2. B 样条曲线(二次或三次)
3. 退出
2、任意绘制带有曲线的二维图形或三维图形。
三、实验代码
Bezier
#include
#include
#include
static GLfloat v[4][2];
static GLfloat width = 600, height = 600;
static GLfloat mousex;
static GLfloat mousey;
static int count = 0;
void Init(){
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
//设置背景颜色
}
void Reshape(GLsizei w, GLsizei h){
glViewport(0, 0, w, h);
width = w;
height = h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1.0, 1.0);
glutPostRedisplay();
}
void bezier(GLfloat vv[4][2], int i){
if (i == 0){
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINE_STRIP);
glVertex2i(vv[0][0], vv[0][1]);
glVertex2i(vv[1][0], vv[1][1]);
glVertex2i(vv[2][0], vv[2][1]);
glVertex2i(vv[3][0], vv[3][1]);
glEnd();
}
else{
i--;
int j;
GLfloat l[4][2];
GLfloat r[4][2];
for (j = 0;j<2;j++){
l[0][j] = vv[0][j];
r[3][j] = vv[3][j];
l[1][j] = (vv[0][j] + vv[1][j]) / 2;
r[2][j] = (vv[2][j] + vv[3][j]) / 2;
l[2][j] = (l[1][j] + (vv[1][j] + vv[2][j]) / 2) / 2;
r[1][j] = (r[2][j] + (vv[1][j] + vv[2][j]) / 2) / 2;
l[3][j] = (l[2][j] + r[1][j]) / 2;
r[0][j] = l[3][j];
}
bezier(l, i);
bezier(r, i);
}
}
void mydisplay(){
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
if (count>1){
glBegin(GL_LINES);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(v[0][0], v[0][1]);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(v[1][0], v[1][1]);
glEnd();
}
if (count>2){
glBegin(GL_LINES);
glColor3f(1.0, 1.0, 0.0);
glVertex2f(v[1][0], v[1][1]);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(v[2][0], v[2][1]);
glEnd();
}
if (count>3){
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 1.0);
glVertex2f(v[2][0], v[2][1]);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(v[3][0], v[3][1]);
glEnd();
}
if ((count>0) && (count<4)){
glBegin(GL_LINES);
glColor3f(0.6, 0.4, 0.7);
glVertex2f(v[count - 1][0], v[count - 1][1]);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(mousex, mousey);
glEnd();
}
else if (count == 4){
GLint vv[4][2];
for (int i = 0;i<4;i++){
vv[i][0] = v[i][0];
vv[i][1] = v[i][1];
}
bezier(v, 5);
}
glutSwapBuffers();
glFlush();
}
void mymouse(int button, int state, int xx, int yy)
{
if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
{
if (count<4)
{
v[count][0] = xx;
v[count][1] = height - yy;
glutPostRedisplay();
count++;
}
}
if ((button == GLUT_RIGHT_BUTTON) && (state == GLUT_DOWN))
count = 0;
glutPostRedisplay();
{
}
}
void mypassive(int xx, int yy)
{
}
mousex = xx;
mousey = height - yy;
if ((count>0) && (count<4)) glutPostRedisplay();
int main(int argc, char** argv)
{
}
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(680, 680);
glutInitWindowPosition(340,-340);
glutInit(&argc, argv);
glutCreateWindow("Bezier");
glutDisplayFunc(mydisplay);
glutReshapeFunc(Reshape);
glutMouseFunc(mymouse);
glutPassiveMotionFunc(mypassive);
glutMainLoop();
return 0;
B 样条曲线
#include
#include
#include
#include
#include
using namespace std;
bool mouseRightIsDown = false;
void Init() {
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
//设置背景颜色
}
void Reshape(int w, int h)
//两个参数:窗口被移动后大小
{
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
struct Point
{
int x, y;
Point() {};
Point(int tx, int ty)
{
}
x = tx;
y = ty;
};
vector p;
double getRatio(double t, double a, double b, double c, double d)
{
}
return a * pow(t, 3) + b * pow(t, 2) + c * t + d;
double caculateSquarDistance(Point a, Point b)
{
}
return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
int getIndexNearByMouse(int x, int y)
{
double precision = 200;
int index = -1;
double Min;
for (int i = 0; i < p.size(); i++)
{
double dis = caculateSquarDistance(p[i], Point(x, y));
if (dis < precision)
{
if (index == -1)
{
}
index = i;
Min = dis;
else if (dis < Min)
{
}
index = i;
Min = dis;
}
}
return index;
}
void Blines(Point a, Point b, Point c, Point d)
{
int n = 500;
double derta = 1.0 / n;
glPointSize(2);
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i <= n; i++)
{
double t = derta * i;
double ratio[4];
ratio[0] = getRatio(t, -1, 3, -3, 1);
ratio[1] = getRatio(t, 3, -6, 0, 4);
ratio[2] = getRatio(t, -3, 3, 3, 1);
ratio[3] = getRatio(t, 1, 0, 0, 0);
double x = 0, y = 0;
x += ratio[0] * a.x + ratio[1] * b.x + ratio[2] * c.x + ratio[3] * d.x;
y += ratio[0] * a.y + ratio[1] * b.y + ratio[2] * c.y + ratio[3] * d.y;
x /= 6.0;
y /= 6.0;
glVertex2d(x, y);
}
glEnd();
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5);
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POINTS);
for (int i = 0; i < p.size(); i++)
glVertex2d(p[i].x, p[i].y);
glEnd();
//画线
glLineWidth(2);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < p.size(); i++)
glVertex2d(p[i].x, p[i].y);
glEnd();
if (p.size() >= 4)
for (int i = 0; i < p.size() - 3; i++)
Blines(p[i], p[i + 1], p[i + 2], p[i + 3]);
glFlush();
}
void keyboard(unsigned char key, int x, int y)
{
}
if (key == GLUT_KEY_LEFT)
exit(0);
if (key == GLUT_KEY_RIGHT)
//退格键
{
}
int index = getIndexNearByMouse(x, y);
if (index == -1)
return;
p.erase(p.begin() + index);
glutPostRedisplay();
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
}
Point t(x, y);
p.push_back(t);
glutPostRedisplay();
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
mouseRightIsDown = true;
if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
mouseRightIsDown = false;
}
void motion(int x, int y)
{
}
if (mouseRightIsDown)
{
}
int index = getIndexNearByMouse(x, y);
if (index == -1)
return;
p[index].x = x;
p[index].y = y;
glutPostRedisplay();
int main(int argc, char *argv[])
{
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(680, 680);
glutInitWindowPosition(340, -340);
glutInit(&argc, argv);
glutCreateWindow("B");
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
曲线图:
#include
#include
#include
#include
#include