Bezier曲线绘制 B样条绘制

/*输入点的个数是可以手动改动的,此程序中输入点的最大值设置为.

*同时,程序实现了键盘的交互,用来控制程序运行过程中的退出、重画等

*/

#include<GL/glut.h>

#include<stdlib.h>

int W,H;   //屏幕的大小

int N =-1;   //贝赛尔曲线的幂次

GLfloat Bfunc[15]={0.0};    //Bernstein多项式的值的数组

GLfloat point[15][2]={0.0};     //存储控制点的坐标



void Init()

{

    //设置清除颜色为白色

    glClearColor(1.0f,1.0f,1.0f,1.0f);

}



void ChangeSize(int w, int h)

{

    GLfloat nRange = 1.0f;

    if(h == 0)    h = 1;

    glViewport(0, 0, w, h);

    W = w;

    H = h;



    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    // 设置修剪空间

    if (w <= h) 

        glOrtho (0.0, 0.0, -nRange*h/w, nRange*h/w, 0.0, 0.0);

    else 

        glOrtho (-nRange*w/h, nRange*w/h, 0.0, 0.0, 0.0, 0.0);



    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

void Bezier()

{

    int i,j,t;   

    GLfloat u;   

    //使用的绘制点坐标

    GLfloat DPoint1[2];   

    GLfloat DPoint2[2];   

    //先将第一个控制点赋给第二个点,为后面的循环做准备

    for(i=0;i<2;i++)

        DPoint2[i]=point[0][i];



    glClear(GL_COLOR_BUFFER_BIT);

    //设置控制点的颜色

    glColor3f(1.0f,0.0f,0.0f);

    //设置控制点的大小

    glPointSize(5);

    //绘制控制点

    glBegin(GL_POINTS);

     for(i=0;i<=N;i++)

    {

        glVertex2fv(point[i]);

    }

    glEnd();



    //设置连接控制点线的颜色

    glColor3f(0.0f, 0.0f, 0.0f);

    //设置连线的宽度

    glLineWidth(3);

    //绘制连线

    glBegin(GL_LINE_STRIP);

       for(i=0;i<=N;i++)

            glVertex2fv(point[i]);

    glEnd();



    //设置Bezier曲线的颜色

    glColor3f(1.0f, 0.0f, 0.0f);

    //设置线宽

    glLineWidth(2);

    for(i=0;i<=1000;i++)

    {

        //获得u值

        u =i / 1000.0;

       //初始化Bfunc数组

        for(t=0;t<=N;t++)

            Bfunc[t]=1.0;

        //第一个点的坐标等于第二个点的坐标,方便下面的绘制

        DPoint1[0]=DPoint2[0];

        DPoint1[1]=DPoint2[1];

        //将第二个坐标的x,y设置为

        DPoint2[0]=0.0;

        DPoint2[1]=0.0;

        //循环、递推计算Bezier基函数的值

        for(j=0;j<=N;j++)

        {

            if(j==0)

            {

                //V0处的Bezier基函数

                Bfunc[j] = 1;

                for(t=N;t>j;t--)

                    Bfunc[j] = Bfunc[j]*(1-u);

            }

            else

            {

                if(i != 1000)

                    Bfunc[j]=(1.0 * ( N - j + 1 ) / j ) * ( u / ( 1 - u ) ) * Bfunc[j-1];  

                else

                {

                    //Bfunc[N]处的Bezier基函数

                    if(j == N)

                        for(t=0;t<N;t++)

                            Bfunc[j]=Bfunc[j]*u;

                    else

                        Bfunc[j]=0.0;

                }

            }

            //获得第二个点的坐标值

            DPoint2[0] = DPoint2[0]+Bfunc[j]*point[j][0];

            DPoint2[1] = DPoint2[1]+Bfunc[j]*point[j][1];

        }

        //连接两点

        if(N>=1)

        {

            glBegin(GL_LINES);

                glVertex2fv(DPoint1);

                glVertex2fv(DPoint2);

            glEnd();

        }

    }

    glFlush();

}



//鼠标事件获得控制点的坐标

void InitMouse(int button,int state,int x,int y)

{

       //如果不是点击鼠标左键的状态,则不获得坐标值

       if(button !=GLUT_LEFT_BUTTON||state !=GLUT_DOWN)

          return;

          if( N < 14 )   

         {

             N++;

            //获得鼠标点击的坐标

            point[N][0] = (2.0*x)/(float)(W-1)-1.0;

            point[N][1] = (2.0*(H-y))/(float)(H)-1.0;

            //重绘

            glutPostRedisplay();

         }

}

//键盘响应

void keyboard(unsigned char key,int x,int y)

{

    switch(key)

      {

        //退出运行系统

        case'q':case'Q':

        exit(0);

        break;

        //重画曲线

        case'c':case'C':

        N = 0;

        glutPostRedisplay();

        break;

        //刷新

        case'e':case'E':

        glutPostRedisplay();

        break;

       }

}

void main(int argc,char* argv[])

{

    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutInitWindowPosition(50,100);

    glutInitWindowSize(800,600);

    glutCreateWindow("Bezier曲线绘制");

    glutReshapeFunc(ChangeSize);

    Init();

    glutDisplayFunc(Bezier);

    glutMouseFunc(InitMouse);

    glutKeyboardFunc(keyboard);

    glutMainLoop();

}

 

 

/*程序实现根据鼠标输入的点进行次B样条曲线的绘制,程序中鼠标

*输入点的个数是可以手动改动的,此程序中输入点的最大值设置为.

*同时,程序实现了键盘的交互,用来控制程序运行过程中的退出、重画等

*/

#include<GL/glut.h>

int W,H;   //屏幕的大小

int N = -1; //控制点的个数 

GLfloat point[25][2]={0.0};     //存储控制点坐标的数组



void Init()

{

    //设置清除颜色为白色

    glClearColor(1.0f,1.0f,1.0f,1.0f);

}



void ChangeSize(int w, int h)

{

    GLfloat nRange = 1.0f;

    if(h == 0)    h = 1;

    // 设置视区尺寸

    glViewport(0, 0, w, h);

    W = w;

    H = h;

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    // 设置修剪空间

    if (w <= h) 

        glOrtho (0.0, 0.0, -nRange*h/w, nRange*h/w, 0.0, 0.0);

    else 

        glOrtho (-nRange*w/h, nRange*w/h, 0.0, 0.0, 0.0, 0.0);



    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

void BSpline()

{

    int i;

    glClear(GL_COLOR_BUFFER_BIT);

    //设置控制点的颜色

    glColor3f(1.0f, 0.0f, 0.0f);

    //设置控制点的大小

    glPointSize(5);

    //绘制控制点

    glBegin(GL_POINTS);

        for(i=0;i<=N;i++)

            glVertex2fv(point[i]);

    glEnd();

    

    //设置连接控制点的线的颜色

    glColor3f(0.0f, 0.0f, 0.0f);

    //设置连线的宽度

    glLineWidth(3);

    //绘制连线

    glBegin(GL_LINE_STRIP);

        for(i=0;i<=N;i++)

            glVertex2fv(point[i]);

    glEnd();

    

    int j,k;

    float a,b,c,d;

    glColor3f(1.0,0.0,0.0);

    //3次B样条曲线,由个控制点控制,循环画出每一段曲线

    for(j=0;j<=N-3;j++)

    {

      glBegin(GL_LINE_STRIP);          

        for(k=0; k<=100;k++)

        {

        float x,y,t;

        t = k/100.0;

        //求基函数的值

        a=(1-t)*(1-t)*(1-t)/6.0;

        b=(3.0*t*t*t-6.0*t*t+4.0)/6.0;

        c=(3.0*t*(1.0+t-t*t)+1.0)/6.0;

        d=t*t*t/6.0;

        //求出曲线上点的坐标

        x=a*point[j][0]+b*point[j+1][0]+c*point[j+2][0]+d*point[j+3][0];

        y=a*point[j][1]+b*point[j+1][1]+c*point[j+2][1]+d*point[j+3][1];

        glVertex2f(x, y);

       }

      glEnd();

    

    }

    glFlush();

}



//鼠标事件获得点的坐标

void InitMouse(int button,int state,int x,int y)

{

     if(button !=GLUT_LEFT_BUTTON||state !=GLUT_DOWN)

          return;

          if( N < 25 )   

         {

             N++;

            //获得鼠标点击的坐标

            point[N][0] = (2.0*x)/(float)(W-1)-1.0;

            point[N][1] = (2.0*(H-y))/(float)(H)-1.0;

            //重绘

            glutPostRedisplay();

         }

    }

//键盘响应

void keyboard(unsigned char key,int x,int y)

{

    switch(key)

      {

        //退出运行系统

        case'q':case'Q':

        exit(0);

        break;

        //重画曲线

        case'c':case'C':

        N = 0;

        glutPostRedisplay();

        break;

        //刷新

        case'e':case'E':

        glutPostRedisplay();

        break;

       }

}



void main(int argc,char* argv[])

{

    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutInitWindowPosition(50,100);

    glutInitWindowSize(800,600);

    glutCreateWindow("B样条绘制");

    glutReshapeFunc(ChangeSize);

    Init();

    glutDisplayFunc(BSpline);

    glutMouseFunc(InitMouse);

    glutKeyboardFunc(keyboard);

    glutMainLoop();

}

 

你可能感兴趣的:(IE)