原创  基于贝塞尔平滑法的改进 收藏

平滑曲线有很大概有多种方法,我也没调查过,不要见怪

这里说的是一种基于贝塞尔平滑法的改进方法。

至于什么是贝塞尔平滑法,可以去www.baidu.com里搜索(其实也就是个函数,后面有代码)

改进后的平滑的效果如下图

A、B、C、D、E是一多边形的五点,红色曲线为平滑结果。个人觉得图中平滑效果已经算好了。
 
说算法其实也很简单:
先说贝塞尔平滑法,函数代码如下:
  public int cni(int i, int n) {
    int j, N = 1, Nn = 1, Ni = 1, Nni = 1;
    for (j = n; j >= 1; j--) Nn = Nn * j;
    for (j = i; j >= 1; j--)   Ni = Ni * j;
    for (j = n - i; j >= 1; j--)   Nni = Nni * j;
    N = Nn / (Ni * Nni);
    return N;
  }
  public void BezierSpline(int n, int m, Graphics g) {
    int k, i, x1 = 0, y1 = 0, x2, y2;
    double x0, y0, t, blend;
    for (k = 0; k <= m; k++) {
      t =1.0*k / m;
      x0 = Math.pow( (1 - t), n) * nx[0];  y0 = Math.pow( (1 - t), n) * ny[0];
      for (i = 1; i < n; i++) {
        blend = cni(i, n) * Math.pow( (1 - t), (n - i)) * Math.pow(t, i);
        x0 += blend * nx[i];     y0 += blend * ny[i];
      }
      x0 += Math.pow(t, n) * nx[n];    y0 += Math.pow(t, n) * ny[n];
      x2 = (int) x0;      y2 = (int) y0;
      if (k > 0)   g.drawLine(x1, y1, x2, y2);
      x1 = x2;      y1 = y2;
    }
  }
上面的代码是JAVA的,学过C语言的也不难看懂。
想要改成C的话,只要把Math.pow()和g.drawLine替换成C里面对应的计算幂的函数和画线的函数就可以了(其实原本是C代码的,被我改成JAVA,现在又要改回C)
函数说明:
public int cni(int i, int n)  是BezierSpline里调用的函数,看清参数类型和返回类型就可以调用了。
BezierSpline()
有三个参数,第一个n是点的个数,第二个m是平滑系数(也就是你想你平滑的曲线由多少条线段组成,当然是越多越平滑,但画线的速度也越慢),第三个是在JAVA APPLET程序才需要的,是指明线条画在哪里的。
函数里的nx[]   ny[]    是两个三维数组,保存了三个坐标的x和y值(这里只传三个坐标进去,就是改进的地方之一)。
下面要做的就是构造不同的三点坐标传进BezierSpline()里去。
把多边形拆成多个夹角,五边形就有5个,每个夹角刚好可以由三个坐标来描述。
例如角EAB,可以由点E、A、B的坐标来描述。
但是这里又做了些改进,去掉E、B点,改由线段EA和线段AB的中点来代替E点和B点
然后把三点传进三维数组nx[]   ny[]    ,调用BezierSpline()
此时只完成了一部分的平滑,再对每个夹角都做这样的处理,
效果就出来了。
呵呵
不知道有没有说清楚,如果您有好的方法,不妨留言来讨论
 

发表于 @ 2006年07月27日 10:15:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:取Run下所有值 | 新一篇:TESTGO !VERY GOOD!

  • 发表评论
  • 评论内容:
  •  
Copyright © Kvci
Powered by CSDN Blog