zoukankan      html  css  js  c++  java
  • 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();
    }
  • 相关阅读:
    安卓开发遇到的报错信息
    工作记录
    答辩系统问题
    DWR
    前端vue 里的tab切换 减少dom操作
    前端拖动div 效果
    vue 点击按钮弹窗,点击关闭按钮关闭弹窗。
    前段开发 jq ajax数据处理详细讲解。
    vue计算属性computed和methods的区别
    前段开发 react native tab功能
  • 原文地址:https://www.cnblogs.com/zhuyaguang/p/4546967.html
Copyright © 2011-2022 走看看