CGPath是否有替代方法,可以为给定位置计算路径上的点?

ope*_*rog 3 math cocoa core-graphics ios quartz-core

对于动画计时算法,我需要提供一条路径作为曲线。两端都有控制点的贝塞尔曲线。

问题在于,由于CGPathRef是不透明的,因此似乎无法在CGPath上计算点。苹果也没有提供任何机制来计算路径上的点。

是否有一个库或实用程序类可以针对给定位置(例如沿路径中间的0.5)计算贝塞尔曲线或路径上的点?

还是让我改一下一下:如果CGPath / CGPathRef因为它是不透明的而使此操作不可能,并且如果您只关心贝塞尔曲线,是否有办法计算路径上的位置点?

Dav*_*ist 5

贝塞尔曲线背后的数学实际上是“正义”:

开始?(1-t)3 + 3?c 1?t(1-t)2 + 3?c 2?t 2(1-t)+结束?t 3

这意味着,如果知道起点,终点和两个控制点(c 1和c 2),则可以计算任意t的值(从0到1)。

如果值是点(如下图所示),则可以分别对x和y进行这些计算。

在此处输入图片说明

这是我在这里对Bézier路径的解释,而随着滑块变化(在Javascript中)而更新橙色圆圈的代码就是这样(将它翻译成Objective-C或简单地翻译成C并不难,但我太懒了):

var sx = 190; var sy = 80; // start
var ex = 420; var ey = 250; // end

var c1x = -30; var c1y = 350; // control point 1
var c2x = 450; var c2y = -20; // control point 2

var t = (x-minSliderX)/(maxSliderX-minSliderX); // t from 0 to 1

var px = sx*Math.pow(1-t, 3) + 3*c1x*t*Math.pow(1-t, 2) + 3*c2x*Math.pow(t,2)*(1-t) + ex*Math.pow(t, 3);
var py = sy*Math.pow(1-t, 3) + 3*c1y*t*Math.pow(1-t, 2) + 3*c2y*Math.pow(t,2)*(1-t) + ey*Math.pow(t, 3);
// new point is at (px, py)
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的,但值得注意的是,与手动乘法相比,`pow()` 函数非常慢。如果你需要计算很多点,它会产生严重的影响(我通常不鼓励过早的优化,但是 pow() 对于平方和立方来说太慢了,它确实值得扩展它所需的小麻烦)。我在以下几篇文章中讨论了 ObjC 中的贝塞尔计算:http://robnapier.net/blog/fast-bezier-intro-701 和 http://robnapier.net/blog/faster-bezier-722。 (2认同)