如何阻止贝塞尔样条曲线超出坐标轴?

时间:2012-04-03 11:56:07

标签: algorithm bezier uibezierpath

在我的iOS应用程序中,我使用一种算法通过一组2D点绘制一个贝塞尔样条曲线,该算法为连接两个连续点的每个贝塞尔曲线计算第一和第二控制点的集合。 该算法运行良好但我的问题是,现在我在带有X和Y轴的图形上显示此曲线。

每当有几个点或在轴上,其余部分在内部时,曲线似乎掉头并越过轴并回到两个点然后穿过两个点和里面的点

从算法的角度来看,没有任何错误。在这种情况下,控制点将在坐标轴的一侧生成。

有没有办法让我可以通过这些点并查看它们中的一些是否在轴上并修改控制点,使得曲线而不是走出曲线只是作为直线穿过轴上的两个点线与坐标轴重合。

1 个答案:

答案 0 :(得分:4)

检测离屏的曲线

贝塞尔曲线实际上只是多项式方程。有multiple types of Bezier curves,对应于曲线的不同程度。

因此,只需获取生成的等式(一个用于x,一个用于y,然后找到根(它们通过的点) 0)。如果根存在,则曲线通过轴。

例如,对于二次(度= 2)贝塞尔曲线,给定我们的三个点(x 0 ,y 0 ),(x 1 < / sub>,y 1 ),(x 2 ,y 2 equations

x(t) = (x0 - 2x1 + x2)t2 - 2(x0 + x1)t + x0
y(t) = (y0 - 2y1 + y2)t2 - 2(y0 + y1)t + y0
0 <= t <= 1

此时,我们可以使用quadratic formula来解析t,并检查解决方案是否存在,或者在[0,1]的{​​{1}}域之外}}。然而,还有另一种方法可以推广三次贝塞尔曲线,而不必触及复杂的cubic formula - 只需检查极值点。这些是导数= 0的点。因为导数是

x'(t) = 2(x0 - 2x1 + x2)t - 2(x0 + x1)
y'(t) = 2(y0 - 2y1 + y2)t - 2(y0 + y1)

这意味着极值在

textrema-x = (x0 + x1) / (x0 - 2x1 + x2)
textrema-y = (y0 + y1) / (y0 - 2y1 + y2)

因此,只需检查x(t extrema-x )&gt; 0和y(t extrema-y )&gt; 0 (我们假设端点x 0 且x 2 已知在屏幕上也称为&gt; 0)。对于三次Bezier曲线,做同样的事情,但使用二次公式来求解极值(在这种情况下,每个tx都有两个极值)


防止曲线离开屏幕

如果我们求解x(t extrema-x )&gt; 0通过我们上面的等式t extrema-x 并将其插入x(t),我们发现在一些代数之后,为了防止穿过x轴,我们需要

-4x0x1 + x0x2 - x12 > 0 if (x0 + x2) > 2x1
-4x0x1 + x0x2 - x12 < 0 if (x0 + x2) < 2x1

(if(x 0 + x 2 )= 2x 1 ,我们从x 0线性移动到x 2 所以,假设两者都是正数,我们不能越过x轴)

有点盯着这些方程会说服你,如果(x 0 + x 2 )&gt; 2x 1 ,我们可以简单地减少x 1 直到满足左手条件; if(x 0 + x 2 )&lt; 2x 1 ,我们可以简单地增加x 1 直到满足条件。 y的等式是类似的。


这告诉我们如何防止曲线离开左侧y和顶部x=0部分屏幕 - 正确的y=0和底部x=screen_width怎么样?

我们可以通过想象我们将屏幕翻转到其镜像来轻松完成此操作,因此右侧为y=screen_height,左侧为x=0。这可以通过在上面的所有等式中用x=screen_width替换x的每个实例来完成,并检查我们的条件。然后,例如,当在第一种情况之前我们减少x 1 时,在这种情况下我们要减少(screen_width-x 1 ),这是与增加 x 1 相同。同样的逻辑适用于将(screen_width-x)替换为y