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();
}
时间: 2024-10-09 21:01:54

Bezier曲线绘制 B样条绘制的相关文章

OpenGL绘制简单的参数曲线——三阶Bezier曲线(二)

今天我们来介绍三次Bezier曲线,这曲线网上资料非常多,我这里只是简单介绍下原理. 在二维空间中(三维也类似),给定n+1个点P0.P1.... .Pn.参数t的n次的Bezier曲线是: 图1 我们根据上面式子可以推出一阶.二阶.三阶贝塞尔曲线,下面是一阶贝塞尔曲线: 图2 下面是二阶贝塞尔曲线,表示的是从P0P1线段取Q0,P1P2线段取Q1,每一个Q0Q1都是曲线的切向量: 图3 下面是三阶贝塞尔曲线,表示的是从P0P1线段取Q0,P1P2线段取Q1,P2P3线段取Q2,再从Q0Q1取R

7.5.5编程实例-Bezier曲线曲面绘制

(a)Bezier曲线                         (b) Bezier曲面 1. 绘制Bezier曲线 #include <GL/glut.h> GLfloat ctrlpoints[4][3] = {{ -4.0, -4.0, 0.0}, { -2.0, 3.0, 0.0}, {2.0, 4.5, 0.0}, {3.0, -3.0, 0.0}}; void init(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glShadeMod

用OpenGL进行曲线、曲面的绘制

实验目的 1)理解Bezier曲线.曲面绘制的基本原理:理解OpenGL中一维.二维插值求值器的用法. 2)掌握OpenGL中曲线.曲面绘图的方法,对比不同参数下的绘图效果差异: 代码1:用四个控制点绘制一条三次Bezier曲线 #include "stdafx.h" #include <stdlib.h> #include <time.h> #include <GL/glut.h> //4个控制点的3D坐标--z坐标全为0 GLfloat ctrl

TWaver3D直线、曲线、曲面的绘制

插播一则广告(长期有效) TWaver需要在武汉招JavaScript工程师若干 要求:对前端技术(JavasScript.HTML.CSS),对可视化技术(Canvas.WebGL)有浓厚的兴趣 基础不好的可培养,基础好的可共谋大事 感兴趣的给我发邮件:[email protected] ————————————————————正文的分割线—————————————————————- 今天来说关于绘图的那些事儿. 先说说绘图引擎的种类.目前市面上绘图引擎大致可以分为两类.一类基于HTML技术,

简单而粗暴的方法画任意阶数Bezier曲线

简单而粗暴的方法画任意阶数Bezier曲线 虽然说是任意阶数,但是嘞,算法原理是可以到任意阶数,计算机大概到100多阶就会溢出了 Bezier曲线介绍 本文代码 背景 在windows的OpenGL环境中,使用鼠标在屏幕上选点,并以点为基础画出Bezier曲线 初始化 鼠标操作 3阶以内Bezier曲线 n阶Bezier曲线 初始化 创建窗口,初始化大小.显示模式.添加显示和鼠标等回调函数,设置背景颜色等. 完成之后,定义两个全局的int类型的vector 用于存储鼠标在窗口中选择的点.同时定义

Bezier曲线(1):Introducion

搬运自我的CSDN https://blog.csdn.net/u013213111/article/details/94067849 参考: 贝塞尔曲线扫盲 贝塞尔曲线的理解 使用贝塞尔曲线绘制多点连接曲线 Bezier curves and surfaces Bezier Curve Drawing Algorithms Construction of Bézier Curves 首先来直观地看一下Bezier曲线是什么样的. 这是个二次Bezier曲线,经过 \(P_0\) 和 \(P_2

Bezier曲线原理—动态解释

Bezier曲线原理 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的.贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等.在Flash4中还没有完整的曲线工具,而在Flash5里面已经提供出贝塞尔曲线工具.贝塞尔曲线于19

清华版CG 实验6 Bezier曲线生成

1.实验目的: 了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法. 2.实验内容: (1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier曲线: (2) 调试.编译.修改示范程序. 3.实验原理: Bezier曲线是通过一组多边形折线的顶点来定义的.如果折线的顶点固定不变,则由其定义的Bezier曲线是唯一的.在折线的各顶点中,只有第一点和最后一点在曲线上且作为曲线的起始处和终止处,其他的点用于控制曲线的形状及阶次.曲线的形状趋向于多

Bezier曲线的实现——de Casteljau算法

这学期同时上了计算机图形学和计算方法两门课,学到这部分的时候突然觉得de Casteljau递推算法特别像牛顿插值,尤其递推计算步骤很像牛顿差商表. 一开始用伯恩斯坦多项式计算Bezier曲线的时候,由于其多项式的计算十分不利于计算机实现,还会出现数值不稳定的情况 所以后来出现了de Casteljau算法,以下PPT截图来自北京化工大学李辉老师  实现代码(六个顶点): import numpy as np import matplotlib.pyplot as plt #B = (1-t)*