Bezier剪辑

时间:2008-09-20 20:56:32

标签: graphics geometry 2d bezier csg

我正在尝试查找/制作算法来计算两个任意填充的2D对象的交集(一个新的填充对象)。使用线或立方贝塞尔定义对象,并且可以具有孔或自相交。我知道几个现有算法对多边形listed here做同样的事情。但是,我想支持beziers而不将它们细分为多边形,并且输出应该与没有交叉点的区域中的输入具有大致相同的控制点。

这是一个交互式程序来做一些CSG,但裁剪不需要是实时的。我已经搜索了一段时间但没有找到好的起点。

4 个答案:

答案 0 :(得分:10)

我发现以下出版物是关于贝塞尔剪辑的最佳信息:

吨。 W. Sederberg,BYU,计算机辅助几何设计课程笔记

第7章讨论了曲线交叉点,可在线获取。它概述了4种不同的方法来查找交叉点,并详细描述了Bezier Clipping:

http://www.tsplines.com/technology/edu/CurveIntersection.pdf

答案 1 :(得分:6)

我知道我有被裁员的风险,但我正在研究同样的问题并找到了一个我在学术论文中读过的解决方案,但没有找到合适的解决方案。

您可以将贝塞尔曲线重写为一组两个双变量三次方程式,如下所示:

  • Δx= ax 1 * t 1 ^ 3 + bx 1 * t 1 ^ 2 + cx 1 * t 1 + dx 1 - ax 2 * t 2 ^ 3 - bx 2 * t 2 ^ 2 - cx 2 * t 2 - dx 2
  • Δy= ay 1 * t 1 ^ 3 +乘1 * t 1 ^ 2 + cy 1 * t 1 + dy 1-ay 2 * t 2 ^ 3 - 乘以2 * t 2 ^ 2 - cy 2 * t 2 - dy 2

显然,曲线与(t 1,t 2)的值相交,其中Δx=Δy= 0.不幸的是,由于难以在二维中找到根,而近似的方法倾向于(如另一位作家说它爆炸了。

但是如果你使用整数或有理数作为控制点,那么你可以使用 Groebner基础将你的双变量3阶多项式重写为(可能是 - 最多 - order-9-because-your-nine-possible-intersectionctions)monovariate polynomial。在那之后你只需要在一个维度上找到你的根(比如说t 2),然后将你的结果插回到你原来的一个方程中,找到另一个维度。

Burchburger对Groebner Bases的外行友好介绍称为“GröbnerBases:系统理论家简介”,这对我非常有帮助。谷歌一下。另一篇有用的论文是由TF Hain称为“快速,精确展平立方Bézier路径和偏移曲线”的论文,它有许多贝塞尔曲线的效用方程,包括如何找到多项式系数对于x和y方程。

至于贝塞尔削波是否有助于这种特殊的方法,我对此表示怀疑,但贝塞尔裁剪是一种缩小交叉点可能位置的方法,而不是找到最终(尽管可能是近似的)答案的方法。使用此方法的大量时间将用于查找单变量方程,并且该任务在剪切时不会变得更容易。相比之下,寻找根源是微不足道的。

然而,这种方法的一个优点是它不依赖于递归细分曲线,并且问题变成了一个简单的一维寻根问题,这不容易,但有很好的记录。主要的缺点是,如果你处理浮点多项式或使用更高阶的贝塞尔曲线,计算Groebner基础是昂贵的并且变得非常笨重。

如果你想在Haskell中找到一些完成的代码来找到交叉点,请告诉我。

答案 2 :(得分:3)

很久很久以前,我编写代码来做这件事。我正在使用作为PostScipt路径生成的分段Bezier边界来定义2D对象的项目。

我使用的方法是:

让曲线p,q由Bezier控制点定义。它们相交吗?

计算控制点的边界框。如果它们不重叠,则两条曲线不相交。否则:

p.x(t),p.y(t),q.x(u),q.y(u)是0 <= t,u <= 1.0的三次多项式。 距离平方(p.x-q.x)** 2 +(p.y-q.y)** 2是(t,u)上的多项式。 使用Newton-Raphson尝试解决零问题。丢弃0 <= t,u <= 1.0

之外的任何解决方案

N-R可能会或可能不会聚。曲线可能不相交,或者当两条曲线几乎平行时,N-R可能会爆炸。因此,如果在经过一些任意次数的迭代之后它没有收敛,则切断N-R。这可能是一个相当小的数字。

如果N-R没有收敛于解,则将一条曲线(例如,p)分成两条曲线pa,pb,t = 0.5。这很容易,它只是计算中点,正如链接文章所示。然后递归测试交叉点的(q,pa)和(q,pb)。 (注意,在递归的下一层中,q已变为p,因此p和q在递归的每一层上交替分开。)

大多数递归调用都会快速返回,因为边界框不重叠。

你必须在某个任意深度处切断递归,以处理两条曲线平行且不完全接触的奇怪情况,但它们之间的距离任意小 - 可能只有1 ULP的差异。

当你找到一个交叉点时,你没有完成,因为三次曲线可以有多个交叉点。所以你必须在交叉点处分割每条曲线,并递归检查(pa,qa),(pa,qb),(pb,qa),(pb,qb)之间的更多相互作用。

答案 3 :(得分:1)

有许多关于做贝塞尔剪裁的学术研究论文:

http://www.andrew.cmu.edu/user/sowen/abstracts/Se306.html

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.6669

http://www.dm.unibo.it/~casciola/html/research_rr.html

我推荐使用区间方法,因为正如您所描述的那样,您不必分解为多边形,并且可以获得有保证的结果以及为结果集定义自己的任意精度。有关间隔渲染的更多信息,您还可以参考http://www.sunfishstudio.com