3

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

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

从算法的角度来看,这并没有错。这种情况下的控制点将在坐标轴之外生成。

有没有一种方法可以让我通过这些点,看看它们中的一些是否在轴上并修改控制点,使曲线而不是超出曲线只是通过轴上的两个点,作为一条与坐标轴。

4

1 回答 1

5

检测到屏幕外的曲线

贝塞尔曲线实际上只是多项式方程。贝塞尔曲线有多种类型,对应曲线的不同度数。

因此,只需获取生成的方程(一个为x,一个为y,并找到根(它们通过 0 的点)。如果根存在,则曲线通过轴。

例如,对于二次 (degree=2) Bezier 曲线,给定我们的三个点 (x 0 , y 0 ), (x 1 , y 1 ), (x 2 , y 2 ),方程

x(t) = (x 0 - 2x 1 + x 2 )t 2 - 2(x 0 + x 1 )t + x 0 
y(t) = (y 0 - 2y 1 + y 2 )t 2 - 2( y 0 + y 1 )t + y 0
0 <= t <= 1

此时,我们可以使用二次公式来求解t,并检查该解是否不存在或者在我们的[0,1]for域之外t。但是,还有另一种方法可以推广三次贝塞尔曲线,而无需触及复杂的三次公式- 只需检查极值点。这些是导数 = 0 的点。因为导数是

x'(t) = 2(x 0 - 2x 1 + x 2 )t - 2(x 0 + x 1 )
y'(t) = 2(y 0 - 2y 1 + y 2 )t - 2(y 0 + y 1 )

这意味着极值在

t极值-x = (x 0 + x 1 ) / (x 0 - 2x 1 + x 2 )
t极值-y = (y 0 + y 1 ) / (y 0 - 2y 1 + y 2 )

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


防止曲线脱离屏幕

如果我们通过将上面的方程对 t extrema-x 代入 x(t)来求解 x(t extrema-x ) > 0 ,经过一些代数后,我们发现,为了防止穿过 x 轴,我们需要

-4x 0 x 1 + x 0 x 2 - x 1 2 > 0 如果 (x 0 + x 2 ) > 2x 1 
-4x 0 x 1 + x 0 x 2 - x 1 2 < 0 如果 (x 0 + x 2 ) < 2x 1

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

稍微看一下这些方程应该会让你相信,如果 (x 0 + x 2 ) > 2x 1,我们可以简单地减少 x 1直到满足左手条件;如果 (x 0 + x 2 ) < 2x 1,我们可以简单地增加 x 1直到满足条件。的等式y是类似的。


这告诉我们如何防止曲线偏离屏幕的左侧( x=0)和顶部( y=0)部分 - 右侧( x=screen_width)和底部( y=screen_height)呢?

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

于 2012-04-03T12:32:32.323 回答