获取二维贝塞尔曲线的法线

Get normal of bezier curve in 2D

我正在尝试用贝塞尔曲线包裹文本,并遵循此 link、http://www.planetclegg.com/projects/WarpingTextToSplines.html

中的教程

我通过这段代码得到导数:

function Derivative(x0,x1,x2,t)
{
   var mt = 1-t;
   var a = mt * mt; 
   var b = mt * t * 2; 
   var c = t * t; 
   var result=a * x0 + b * x1 + c * x2;
   return result;
}

所以我用这段代码计算法线:

function Normal(x0,x1,x2,y0,y1,y2,t) 
{      
  var dx = Derivative(x0,x1,x2,t);     
  var dy = Derivative(y0,y1,y2,t);  

  var q = Math.sqrt(dx*dx + dy*dy)
  return { x: -dy/q, y: dx/q };
};

所以这是结果:有些地方错了,但我不知道在哪里。

谢谢大家!

"what I want"图像看起来很像我的bezierjs documentation,所以:你的想法是正确的(取导数得到切向量,然后旋转得到法线),但是一定要把那些衍生品弄对。

如果您使用由三个二维点 P1、P2 和 P3 组成的二次贝塞尔曲线,则贝塞尔函数为:

P1 * (1-t)² + P2 * 2 * (1-t)t + P3 * t²

导数(仅以多种方式之一编写)为:

P1 * (2t-2) + (2*P3-4*P2) * t + 2 * P2

你显示的导数计算代码实际上是常规的二次贝塞尔函数,所以这会给你相当错误的结果。将代码更新为正确的导数,应该没问题。

Pomax 的答案就是您所需要的,但如果您需要一些代码,这里有一些在 Javascript:

中实现的实用方法
// these methods are only for quadratic curves

// p1: {x,y} start point
// pc: {x,y} control point    
// p2: {x,y} end point
// t: (float between 0 and 1) time in the curve

getPointAt(t, p1, pc, p2) {
    const x = (1 - t) * (1 - t) * p1.x + 2 * (1 - t) * t * pc.x + t * t * p2.x
    const y = (1 - t) * (1 - t) * p1.y + 2 * (1 - t) * t * pc.y + t * t * p2.y

    return { x, y };
}

getDerivativeAt(t, p1, pc, p2) {
    const d1 = { x: 2 * (pc.x - p1.x), y: 2 * (pc.y - p1.y) };
    const d2 = { x: 2 * (p2.x - pc.x), y: 2 * (p2.y - pc.y) };

    const x = (1 - t) * d1.x + t * d2.x;
    const y = (1 - t) * d1.y + t * d2.y;

    return { x, y };
}

getNormalAt(t, p1, pc, p2) {
    const d = getDerivativeAt(t, p1, pc, p2);
    const q = sqrt(d.x * d.x + d.y * d.y);

    const x = -d.y / q;
    const y = d.x / q;

    return { x, y };
}

https://jsfiddle.net/Lupq8ejm/1/