计算机图形学N次Bezier曲线绘制的理解及代码(基于OpenGL和vc)

二次Bezier曲线

三次Bezier曲线

n次Bezier曲线

 

的函数

double B(int n,int i,float t){
    int sum=1;
    if(i==n||i==0) return pow(t,i)*pow(1-t,n-i);
    int j;
    for(j=n-i+1;j<=n;j++)
        sum*=j;
    for(j=1;j<=i;j++)
        sum/=j;
    return sum*pow(t,i)*pow(1-t,n-i);
}

主要步骤:

1.通过init()函数生成NUM_POINTS个控制顶点(NUM_POINTS在cpp文件开始的define处可以更改),并存入vec[]数组中

2.将控制顶点依次连线,之后标注各个控制顶点。

3.将vec[0]赋给p_current,由定义,将t由0逐渐增加至1,对于每一个t值,求出一个点保存至p,连接p,p_current画线,之后再将p赋给p_current。

代码如下:(也可以通过这个链接支付积分下载:https://download.csdn.net/download/qq_42276781/11081655

#include<windows.h>
#include <math.h>
#include <GL/glut.h>
#include <iostream>
#define NUM_POINTS 6//n次Bezier则修改NUM_POINTS为n+1
struct Point2{
    double x;
    double y;

    Point2() { ; }
    Point2(int px, int py) { x = px; y = py; }
    void SetPoint2(int px, int py) { x = px; y = py; }
};

/*全局变量*/
Point2 vec[NUM_POINTS];//定义点数组
bool mouseLeftDown = false;//初始化鼠标状态

double B(int n,int i,float t){
    int sum=1;
    if(i==n||i==0) return pow(t,i)*pow(1-t,n-i);
    int j;
    for(j=n-i+1;j<=n;j++)
        sum*=j;
    for(j=1;j<=i;j++)
        sum/=j;
    return sum*pow(t,i)*pow(1-t,n-i);
}
Point2 setBezier(float t){
    Point2 p;
    p.x=0;
    p.y=0;
    /*三次Bezier各项系数
    double a0=pow((1-t),3);
    double a1=pow((1-t),2)*3*t;
    double a2=3*t*t*(1-t);
    double a3=t*t*t;
    */
    //对于四个定点,给定t,得到p的坐标
    //p.x=a0*p0.x+a1*p1.x+a2*p2.x+a3*p3.x;
    //p.y=a0*p0.y+a1*p1.y+a2*p2.y+a3*p3.y;
    for(int k=0;k<=NUM_POINTS;k++){
        p.x+=vec[k].x*B(NUM_POINTS-1,k,t);
        p.y+=vec[k].y*B(NUM_POINTS-1,k,t);
    }
    return p;
}
void setPoint(){//画点
    glPointSize(10.0f);
    glColor3f(0.0, 0.0, 1.0);//颜色蓝(三个参数分别为R G B
    glBegin(GL_POINTS);
    for(int b = 0;b < NUM_POINTS; b++)
        glVertex2f(vec[b].x, vec[b].y);
    glEnd();
}
void setLine(Point2 f,Point2 g){//画线
    glLineWidth(1.5f);
    glBegin(GL_LINE_STRIP);
    glVertex2f(f.x,f.y);
    glVertex2f(g.x,g.y);
    glEnd();
}
void display(){
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();

    glColor3f(1.0,0.0,0.0);
    for(int a=0;a<NUM_POINTS-1;a++)
        setLine(vec[a],vec[a+1]);
    setPoint();
    
    Point2 p_current=vec[0];
    for(float c=0;c<=1;c+=0.05){
        Point2 p=setBezier(c);
        setLine(p_current,p);
        //glFlush();
        p_current=p;
    }
    
    glFlush();
    glutSwapBuffers();
}

void init(){//初始化
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glShadeModel(GL_FLAT);
    for(int d=0;d<NUM_POINTS;d++)
        vec[d].SetPoint2(10+100*d, 500-5*d*d);//生成不在同一直线的若干点
    
}

void reshape(int w, int h){
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLsizei)w, (GLsizei)h, 0.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void mouse(int button, int state, int x, int y){
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        mouseLeftDown = true;

    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
        mouseLeftDown = false;

}

double distance(int x1, int y1, int x2, int y2){
    return sqrt((x1-x2) * (x1 -x2) + (y1-y2) * (y1-y2));
}

void motion(int x, int y){
    if (mouseLeftDown){
        for (int c = 0; c < NUM_POINTS; c++){
            if (distance(vec[c].x, vec[c].y, x, y) < 20)
                vec[c].SetPoint2(x, y);
        }
    }

    glutPostRedisplay();
}

int main(int argc, char **argv){
    
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);
    glutInitWindowSize(600,600);
    glutInitWindowPosition(100,100);
    glutCreateWindow("Bezier");

    init();

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutMainLoop();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42276781/article/details/89301281