平滑曲线有很大概有多种方法,我也没调查过,不要见怪
这里说的是一种基于贝塞尔平滑法的改进方法。
至于什么是贝塞尔平滑法,可以去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 | | 编辑|
举报| 收藏