Amo*_*kar 3 algorithm bezier uibezierpath
在我的 iOS 应用程序中,我使用一种算法通过一组 2D 点绘制一条贝塞尔曲线,该算法为连接两个连续点的每个贝塞尔曲线计算一组第一和第二控制点。该算法工作出色,但我的问题是现在我在带有 X 和 Y 轴的图形上显示这条曲线。
每当有几个点或在轴上,其余的在里面时,曲线似乎掉头并超出轴,然后通过两个点和里面的点返回。
从算法的角度来看,这没有错。在这种情况下,控制点将在坐标轴之外生成。
有没有办法可以通过这些点并查看它们中的一些是否在轴上并修改控制点,以便曲线而不是曲线外的曲线只是通过轴上的两个点作为一条直线与坐标轴。
贝塞尔曲线实际上只是多项式方程。贝塞尔曲线有多种类型,对应曲线的不同程度。
因此,只需取生成的方程(一个为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]的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)。对于三次贝塞尔曲线,做同样的事情,但使用二次公式来求解极值(在这种情况下,每个x和都有两个极值y)。
如果我们通过将上面的 t extrema-x方程代入 x(t) 来求解 x(t extrema-x ) > 0 ,我们会在一些代数之后发现,为了防止穿过 x 轴,我们需要
-4x 0 x 1 + x 0 x 2 - x 1 2 > 0 if (x 0 + x 2 ) > 2x 1 -4x 0 x 1 + x 0 x 2 - x 1 2 < 0 if (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)。