计算三次贝塞尔曲线的拐点?

5 math graphics geometry bezier

我有四个点构成三次贝塞尔曲线:

P1 = (10, 5)
P2 = (9, 12)
P3 = (24, -2)
P4 = (25, 3)
Run Code Online (Sandbox Code Playgroud)

现在我想找到这条曲线的拐点。我用谷歌搜索和/但每个人都指的是一个网站:http://www.caffeineowl.com/graphics/2d/vectorial/cubic-inflexion.html

不幸的是,这些小程序无法工作,我根本无法将它们组合在一起。有人可以告诉我如何计算曲线的拐点吗?

在此输入图像描述

Mik*_*ans 4

详细说明 MBo 的答案,C(t) = X\' * Y\'\' - X\'\' * Y\' = 0这几乎是您想要的伪代码,因为一阶和二阶导数非常容易计算。

\n\n

根据贝塞尔导数的解释以及坐标为 (x1,y1)...(x4,y4) 的通用贝塞尔函数,我们得到:

\n\n
fx(t) = x1 (1-t)\xc2\xb3 + 3\xc2\xb7x2\xc2\xb7(1-t)\xc2\xb2\xc2\xb7t + 3\xc2\xb7x3\xc2\xb7(1-t)\xc2\xb7t\xc2\xb2 + x4\xc2\xb7t\xc2\xb3\nfx\'(t) = a\xc2\xb7(1-t)\xc2\xb2 + 2\xc2\xb7b\xc2\xb7(1-t)\xc2\xb7t + c\xc2\xb7t\xc2\xb2\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中 a = 3(x2-x1)、b = 3(x3-x2) 和 c = 3(x4-x3),并且:

\n\n
fx\'\'(t) = u\xc2\xb7(1-t) + v\xc2\xb7t\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中 u = 2(ba) 且 v = 2(cb)。当然,y 分量也是如此:

\n\n
fy(t) = y1 (1-t)\xc2\xb3 + 3\xc2\xb7y2\xc2\xb7(1-t)\xc2\xb2\xc2\xb7t + 3\xc2\xb7y3\xc2\xb7(1-t)\xc2\xb7t\xc2\xb2 + y4\xc2\xb7t\xc2\xb3\nfy\'(t) = a\'\xc2\xb7(1-t)\xc2\xb2 + 2\xc2\xb7b\'\xc2\xb7(1-t)\xc2\xb7t + c\'\xc2\xb7t\xc2\xb2\nfy\'\'(t) = u\'\xc2\xb7(1-t) + v\'\xc2\xb7t\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中与值a\'相同,但具有值等。ay

\n\n

计算数学C(t) = fx\'(t)\xc2\xb7fy\'\'(t) - fx\'\'(t)\xc2\xb7fy\'(t)很烦人,但这就是我们拥有计算机的原因。如果您拥有树莓派,那么您就拥有 Mathematica 的许可证,所以让我们使用它:

\n\n

在此输入图像描述

\n\n

这是一个庞大的公式,但是找到“任意”曲线的拐点有点愚蠢,因为贝塞尔曲线对于线性仿射变换是不变的,所以t我们检查“真实曲线”,拐点的值都保持不变“或者我们是否旋转/平移/缩放曲线,以便它具有更方便的坐标。就像对其进行平移,使得 (x1,y1) 最终成为 (0,0),并且 (x4,y4) 位于 x 轴上,因此 y4 为零。

\n\n

如果我们这样做,那么我们会得到一个简单得多的公式:

\n\n

在此输入图像描述

\n\n

这简单多少?出色地:

\n\n
18 times:\n  -     x3 * y2\n  + 3 * x3 * y2 * t\n  - 3 * x3 * y2 * t^2\n  -     x4 * y2 * t\n  + 2 * x4 * y2 * t^2\n  +     x2 * y3\n  - 3 * x2 * y3 * t\n  + 3 * x2 * y3 * t^2\n  -     x4 * y3 * t^2\n
Run Code Online (Sandbox Code Playgroud)\n\n

由于我们正在编程,其中有大量可缓存的值。服用:

\n\n
a = x3 * y2\nb = x4 * y2\nc = x2 * y3\nd = x4 * y3\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们可以简化C(t)为:

\n\n
1/18 * C(t) = -a + 3at - 3at^2 - bt + 2bt^2 + c - 3ct + 3ct^2 - dt^2\n= -3at^2 + 2bt^2 + 3ct^2 - dt^2 + 3at - bt - 3ct - a + c\n= (-3a + 2b + 3c - d)t^2 + (3a - b - 3c)t + (c - a)\n
Run Code Online (Sandbox Code Playgroud)\n\n

将因子 18 放回原处,这只是一个简单的二次公式,我们可以使用具有更简单值的二次根恒等式来求根:

\n\n
v1 = (-3a + 2b + 3c - d) * 18\nv2 = (3a - b - 3c) * 18\nv3 = (c - a) * 18\n
Run Code Online (Sandbox Code Playgroud)\n\n

并且,假设3a +d 不等于 2b+3c(因为如果是这种情况则没有根),我们得到:

\n\n
  sqr = sqrt(v2^2 - 4 * v1 * v3)\n    d = 2 * v1\nroot1 =  (sqr - v2) / d\nroot2 = -(sqr + v2) / d\n
Run Code Online (Sandbox Code Playgroud)\n\n

扔掉不属于贝塞尔区间 [0,1] 的根,剩下的就是t原始曲线变形的值。

\n\n
\n

只是我无法以某种方式将事物组合在一起,以便最终得到一些漂亮的伪代码。这也是我给出一些点和坐标的原因。我希望看到有人用实数计算这个

\n
\n\n

尤其是在 Stackoverflow 上,最好不要预先偷懒,而是致力于可能必须学习新事物。

\n