将三次贝塞尔曲线转换为基数样条曲线并返回

Converting a cubic bezier curves into a cardinal spline and back

我看过很多介绍如何将基数或规范样条曲线转换为三次贝塞尔曲线的文章,例如 this 一篇。

有没有办法做相反的事情,即将一组三次贝塞尔曲线转换为基数样条曲线?例如,我们知道每条曲线的端点都在样条曲线上。

我正在寻找一种在信息丢失最少的情况下往返两种表示的方法。理想情况下,解决方案应该是稳定的,以便从三次贝塞尔曲线 => 基数样条曲线 => 三次贝塞尔曲线 => 基数样条曲线在第二次操作后应该产生相同(或几乎相同)的曲线。

想象一下 B 点和 E 点之间的三次曲线。
如果定义为张力参数为s的基数样条,则这些点的切向量为

Tb = s * (E - A)
Te = s * (F - B)

如果曲线定义为贝塞尔曲线,则切向量为

Tb = 3 * (C - B)
Te = 3 * (E - D)

如果曲线BE相同,则切线值相等,如果已知A,B,E,F,s,就可以找到贝塞尔曲线的控制点。反之亦然——如果已知 B、C、D、E、s,我们可以找到基数样条的 A、F 点。比如贝塞尔曲线的第一个控制点是

C = B + s * (E - A ) / 3

--

根据上面 MBo 的回答,贝塞尔曲线 -> 基数的公式是:

A = E - (C - B) * 3 / 秒
F = (E - D) * 3 / s + B

以防万一您不想考虑太多,这里有一个超级简单的方法。可以这么说,贝塞尔曲线实际上只是一条样条曲线。诀窍是简化样条指令:

一些 java 风格...假设您有一个带参数的 drawSpline 函数 drawSpline(int degree, double[] controlPoints, double[] knots);

立方:

 double controlPoints[] = {start.x, start.y, handleA.x, handleA.y, handleB.x, handleB.y, end.x, end.y};
 double knots[] = {0,0,0,0,1,1,1,1};
 drawSpline(3, controlPoints, knots);

二次方:

double controlPoints[] = {start.x, start.y, handle.x, handle.y, end.x, end.y};
double knots[] = {0,0,0,1,1,1};
drawSpline(2, controlPoints, knots);

这可能是识别您可能必须如何处理它的最简单方法。它确实比某些听起来容易得多。然而,如果样条曲线有更多结点,从样条曲线向后到贝塞尔曲线可能会有点棘手。不过,以上内容可能会提供一些指导。

希望对您有所帮助!