2010-04-11 37 views
3

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

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

回答

4

paper by Charles Loop and Jim Blinn进入很多细节上你的问题。

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

+0

唉,链接已经死了,吉姆。这是一样的:http://research.microsoft.com/en-us/um/people/cloop/loopblinn05.pdf – Pierre 2013-09-12 16:23:22

+0

链接更新,h/t @Pierre。 – brainjam 2013-09-13 02:42:15

2

我想补充说,镶嵌选项非常有效,并且可以提供出色的结果。用线段近似贝塞尔曲线听起来是错误的,因为你认为输出看起来像一个多边形。诀窍是使线段足够短,以便误差非常小(比如,小于1/10像素)。

这里是我已用于计算步长大小,以确保最大误差(即,从真曲线线段的偏差)小于增量的公式:

设(X1,Y1) ,(X2,Y2),(X3,Y3),(X4,Y4)是贝塞尔曲线的控制点,在像素coordinates.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); 
    } 

然后小量是你的步长:如果您选择线段的端点在t = 0,T =ε,T = 2 *ε,...,(和在t最后的终点= 1),那么线段将在原始曲线的增量内。

选择增量= 0.1,您会得到与原始曲线在视觉上难以区分的位图输出。