如何将闭合贝塞尔曲线转换为位图?

时间:2010-04-11 14:54:02

标签: algorithm math bezier

我需要一种算法将闭合贝塞尔曲线(可能是自交叉)转换为二进制位图:0表示内部像素,1表示外部像素。我正在编写一个代码,需要在bezier曲线上实现一些操作,有人可以给我一些关于beziere的资源或教程吗?维基百科和其他人没有说任何关于优化,减法,联合,结插入和删除以及其他操作: - )

alt text http://www.imagechicken.com/uploads/1271001073057545100.jpg

2 个答案:

答案 0 :(得分:4)

paper by Charles Loop and Jim Blinn详细介绍了您的问题。

另一种选择是将贝塞尔曲线细分为线段,然后使用您最喜欢的多边形填充算法。

答案 1 :(得分:2)

我想补充说,曲面细分选项非常有效,并且效果非常好。按线段逼近贝塞尔曲线听起来是错误的,因为您认为输出看起来像多边形。诀窍是使线段足够短以使误差非常小(例如,小于1/10像素)。

这是我用来计算步长的公式,以确保最大误差(即线段与真实曲线的偏差)小于delta:

令(x1,y1),(x2,y2),(x3,y3),(x4,y4)为贝塞尔曲线的控制点,以像素坐标为单位.j

  dd0 = square(x1-2*x2+x3) + square(y1-2*y2+y3);
  dd1 = square(x2-2*x3+x4) + square(y2-2*y3+y4);
  dd = 6*sqrt(max(dd0, dd1));

然后dd是曲线上二阶导数的最大值 - 因为三次方的二阶导数是一个线性函数,这个最大值必须出现在一个端点上。这里我使用square(x)作为x * x的缩写。

  if (8*delta > dd) {
    epsilon = 1;
  } else {
    epsilon = sqrt(8*delta/dd);
  }

然后epsilon是你的步长:如果你选择t = 0时线段的端点,t = epsilon,t = 2 * epsilon,...,(和t = 1时的最后一个端点),那么线段将在原始曲线的增量范围内。

选择delta = 0.1,您将获得与原始曲线无法区分的位图输出。