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

4
我正在尝试将文本包裹在贝塞尔曲线中,并按照此链接的教程进行操作: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 };
};

所以这是结果:出了问题,但我不知道在哪里。

查看图片

谢谢大家!


Derivative()函数基本上是使用(x0,y0),(x1,y1)和(x2,y2)作为控制点来评估二次贝塞尔曲线。因此,如果您认为它用于计算另一条曲线的导数,那么您脑海中的曲线很可能实际上是一个三次贝塞尔曲线。如果是这种情况,您将需要传入x0=P1x-P0x,x1=P2x-P1x和x2=P3x-P2x(y0、y1、y2值相同),其中P0、P1、P2和P3是三次贝塞尔曲线的控制点。 - fang
实际上,立方到二次是P0,2/3 P0到P1,2/3 P2到P1,P2; - geowar
2个回答

5

"我所想要的"图像非常类似于我的bezierjs文档,因此:你有了正确的想法(取导数以获得切向量,然后旋转以获得法向量),但务必确保获得正确的导数。

如果您正在使用由三个2D点P1、P2和P3组成的二次Bezier曲线,则Bezier函数为:

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

导数(有许多种写法)为:

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

您展示的导数计算代码实际上是常规二次贝塞尔函数,因此会给您带来错误的结果。更新代码至正确的导数,您将拥有更好的效果。


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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接