Javascript 尝试查找具有4个点的bezier曲线的长度

Javascript 尝试查找具有4个点的bezier曲线的长度,javascript,math,canvas,bezier,Javascript,Math,Canvas,Bezier,对于这个问题,我已经找到了大约1000个答案,但没有一个我可以使用,因为我在曲线上使用了4个控制点 也就是说,我偶然发现了这个家伙: 看起来这是一个完美的解决方案,但开头的部分让我完全困惑: k1 = -p1 + 3*(p2 - p3) + p4; k2 = 3*(p1 + p3) - 6*p2; k3 = 3*(p2 - p1); k4 = p1; 我究竟应该如何在二维对象上进行加法、减法和乘法之类的操作(我假设point2d是一种类似{x:0,y:0}的对象结构)?我觉得自己很蠢,但这是唯

对于这个问题,我已经找到了大约1000个答案,但没有一个我可以使用,因为我在曲线上使用了4个控制点

也就是说,我偶然发现了这个家伙:

看起来这是一个完美的解决方案,但开头的部分让我完全困惑:

k1 = -p1 + 3*(p2 - p3) + p4;
k2 = 3*(p1 + p3) - 6*p2;
k3 = 3*(p2 - p1);
k4 = p1;
我究竟应该如何在二维对象上进行加法、减法和乘法之类的操作(我假设point2d是一种类似
{x:0,y:0}
的对象结构)?我觉得自己很蠢,但这是唯一阻止我真正实现这个怪物的东西


FWIW,我用这个方程来规范一个实体在游戏中穿越曲线时的速度。如果你知道一个更好的方法,我洗耳恭听。

一个二维物体,或点2D,只是一个向量,在数学上有很好的定义。例如:

          k*(x,y) = (k*x, k*y)
           -(x,y) = (-1)*(x,y)
(x1,y1) + (x2,y2) = (x1+x2, y1+y2)

这些都是计算
k1
k2
k3
,和
k4
以下是如何匀速通过三次贝塞尔曲线的公式

没有一个简单的公式可以获得沿三次贝塞尔曲线的偶数长度线段(表示偶数弧长线段)。所涉及的是沿曲线计算多个点,然后使用插值将每个点“推”成大致等距

你不用拿到数学博士学位,我就能让你几乎达到目标

首先,使用通用公式计算从t=0到t=1的曲线上的x/y点,其中t=0表示曲线的起点,t=1表示曲线的终点。这是常见的公式:

// calc the x/y point at t interval
// t=0 at startPt, t=1 at endPt
var x=CubicN(t,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(t,startPt.y,controlPt1.y,controlPt2.y,endPt.y);

// cubic helper formula at t interval
function CubicN(t, a,b,c,d) {
    var t2 = t * t;
    var t3 = t2 * t;
    return a + (-a * 3 + t * (3 * a - a * t)) * t
    + (3 * b + t * (-6 * b + b * 3 * t)) * t
    + (c * 3 - c * 3 * t) * t2
    + d * t3;
}
如果你计算了足够的间隔,比如说100个间隔(每个循环t+=0.01),那么你将得到一个非常好的曲线近似值

这意味着如果你用线连接100个点,结果会非常像一条三次贝塞尔曲线

但你还没做完

上述计算的x/y点系列彼此之间的弧距离不一致。

有些相邻点靠得很近,有些相邻点相距较远

要计算均匀分布的点,请执行以下操作:

  • 用直线连接所有点(创建多段线)
  • 计算该多段线的总距离(T)
  • 将(T)除以所需的均匀段数,得到均匀段长度(SL)
  • 最后,从起点到终点走多段线,计算与上一点的(SL)距离
  • 结果:可以使用这些等距点来遍历曲线


    额外的改进:这将导致沿贝塞尔路径的视觉平滑移动。但是如果你想要更平滑,只需计算100多个点——更多点==更平滑。

    这不是TS提出的问题。这是他的问题的一部分,“我到底应该如何在二维物体上做加法、减法和乘法?”问题:我到底应该如何做加法、减法和乘法等运算,在二维对象上进行减法和乘法?回答:你一次在一个坐标(x或y)上做这些,只是为了尝试扩展第4点,让其他任何人(像我一样)都难以理解。在我的例子中,我从不同的时间间隔中抽取了10个样本(在上面的例子中,用“t”表示)。当我得到“SL”时,我不是将每个样本除以10,而是将其除以区间平均长度的结果。方程类似于
    区间(t)/(区间长度/所有区间的平均长度)
    。您可能还需要调整十的幂,但我不确定这是肯定的还是仅限于我的情况。
    // calc the x/y point at t interval
    // t=0 at startPt, t=1 at endPt
    var x=CubicN(t,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
    var y=CubicN(t,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
    
    // cubic helper formula at t interval
    function CubicN(t, a,b,c,d) {
        var t2 = t * t;
        var t3 = t2 * t;
        return a + (-a * 3 + t * (3 * a - a * t)) * t
        + (3 * b + t * (-6 * b + b * 3 * t)) * t
        + (c * 3 - c * 3 * t) * t2
        + d * t3;
    }