bezier曲线解析与代码(c++)

前言:

        作为rhino重度用户,我对于nurbs建模早有耳闻,但对于何为nurbs却不得其解。最近借上《计算机辅助设计》课程的机会,对此作了一些深入的学习,于是在此记录一下一些课程笔记和课后思考。了解nurbs,主要对于三个概念的理解:bezier曲线、B样条曲线、nurbs曲线与曲面。本文先介绍一下bezier曲线,分为原理解释和代码分享(c++)两部分。

bezier曲线原理

        自由曲线的一般绘制方法是先画控制点,再由控制点共同作用得到曲线。

        

 

         也就是说曲线上每个点的坐标可以由控制点坐标映射得到。 即:

         伯恩斯坦基底多项式

        所以关键在于系数B应该如何确定,bezier曲线使用伯恩斯坦基底作为系数。以下是伯恩斯坦基底多项式的表达式:

         bezier曲线参数方程

        用控制点的坐标乘以对应的伯恩斯坦基底,就得到了bezier曲线的参数方程。

         

也可以写作:

         即:

 

        有理bezier曲线

        刚刚的公式描述的bezier曲线是均匀的,每个控制点的权重相同。我们可以为每个控制点设置一个权重,这样得到了有理bezier曲线。

        w表示对应控制点的权重

代码分享

        我用c++实现了简单的bezier曲线绘制,由于c++绘图太麻烦,这里还使用了easyx库。由于只是为了理解原理,所以我是通过画出曲线上100个点的位置,来代表曲线。核心代码如下:(这里要注意,公式里的n指的是曲线的次数,等于控制点数量-1。)

void bezier(POINT *pts,int len) {//绘制bezier曲线
  int n = len - 1;//公式中的n是控制点数减一
  for (double t = 0;t < 1;t += 0.002) {
    double Bt = 0;double Xt = 0;double Yt = 0;
    for (int i = 0;i <= n; i++) {
      Bt = fact(n)/(fact(n-i)*fact(i))*pow((1-t),(n-i))*pow(t,i);//计算伯恩斯坦基底
      Xt += Bt * (pts[i].x);
      Yt += Bt * (pts[i].y);
    }
    fillcircle(Xt, Yt, 1);
  }
}

 完整代码如下:

#include <graphics.h>    // Reference graphics library header file
#include <conio.h>
#include<iostream>
#include<math.h>
using namespace std;
​
int fact(int n) {//阶乘函数
  if (n == 0) {
    return 1;
  }
  else {
    int res = 1;
    for (int i = n;i > 0;i--) {
      res *= i;
    }
    return res;
  }
}
​
void bezier(POINT *pts,int len) {//绘制bezier曲线
  int n = len - 1;//公式中的n是控制点数减一
  for (double t = 0;t < 1;t += 0.002) {
    double Bt = 0;
    double Xt = 0;
    double Yt = 0;
    for (int i = 0;i <= n; i++) {
      Bt = fact(n)/(fact(n-i)*fact(i))*pow((1-t),(n-i))*pow(t,i);//计算伯恩斯坦基底
      Xt += Bt * (pts[i].x);
      Yt += Bt * (pts[i].y);
    }
    fillcircle(Xt, Yt, 1);
  }
}
​
int main()
{
  initgraph(1000,800);  // 创建画布
  POINT a[] = { {100,200},{350,600},{600,200},{850,600} };
  int len = sizeof(a) / sizeof(a[0]);
  setfillcolor(WHITE);//设置画笔颜色、填充颜色
  setlinecolor(WHITE);
  for (int i = 0;i < len;i++) {
    fillcircle(a[i].x, a[i].y, 3);//画出控制点的位置
  }
  polyline(a,4);//画出控制点的连线
​
  setfillcolor(RED);//设置画笔颜色、填充颜色
  setlinecolor(RED);
  bezier(a,len);//绘制bezier曲线
  _getch();        // Press any key to continue
  closegraph();      // Close the graphics window
  return 0;
}

        运行效果如下:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值