在2D中获得贝塞尔曲线的法线

时间:2016-07-21 08:40:39

标签: curve bezier

我正在尝试以bezier曲线包装文本并按照此链接中的教程http://www.planetclegg.com/projects/WarpingTextToSplines.html

我通过以下代码获得Derivative:

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;
}

所以我用这段代码计算Normal:

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 };
};

所以这就是结果:错误但我不知道在哪里。

See image

谢谢大家!

2 个答案:

答案 0 :(得分:3)

“我想要的”图像看起来很像我的bezierjs documentation,所以:你有正确的想法(取导数得到切线向量,然后旋转得到法线),但要确保得到那些衍生物。

如果你使用二次贝塞尔曲线,包括三个2d点P1,P2和P3,那么贝塞尔函数是:

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

和衍生物(用多种方式之一编写)是:

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

您显示为衍生计算的代码实际上是常规的二次贝塞尔函数,因此会给您带来相当错误的结果。将代码更新为正确的派生词,你应该没问题。

答案 1 :(得分:2)

Pomax的答案就是你所需要的,但如果你关心一些代码,这里有一些在Javascript中实现的util方法:

// 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/

Quadratic curve with normals