码迷,mamicode.com
首页 > 其他好文 > 详细

Bezier曲线绘制 B样条绘制

时间:2015-06-02 19:30:50      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

/*输入点的个数是可以手动改动的,此程序中输入点的最大值设置为.
*同时,程序实现了键盘的交互,用来控制程序运行过程中的退出、重画等
*/
#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)
      {
        //退出运行系统
        caseq:caseQ:
        exit(0);
        break;
        //重画曲线
        casec:caseC:
        N = 0;
        glutPostRedisplay();
        break;
        //刷新
        casee:caseE:
        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)
      {
        //退出运行系统
        caseq:caseQ:
        exit(0);
        break;
        //重画曲线
        casec:caseC:
        N = 0;
        glutPostRedisplay();
        break;
        //刷新
        casee:caseE:
        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();
}

 

Bezier曲线绘制 B样条绘制

标签:

原文地址:http://www.cnblogs.com/zhuyaguang/p/4546967.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!