理解三次插值的实现

时间:2015-01-19 20:26:57

标签: javascript algorithm math interpolation

我想在javascript中实现三次插值,用画布绘制曲线。我们的想法是在画布上单击以添加点,并且每次更改时都会调用一个重绘函数,该函数计算在画布中为给定的点击点绘制的点。

我找到了一些例子:

http://snipplr.com/view/727/cubic-interpolation/

http://www.paulinternet.nl/?page=bicubic

http://dzone.com/snippets/cubic-interpolation

但我不知道如何使用此代码:/

根据这个简单的例子得出4分:

float cubic_interpolate( float y0, float y1, float y2, float y3, float mu ) {

   float a0, a1, a2, a3, mu2;

   mu2 = mu*mu;
   a0 = y3 - y2 - y0 + y1; //p
   a1 = y0 - y1 - a0;
   a2 = y2 - y0;
   a3 = y1;

   return ( a0*mu*mu2 + a1*mu2 + a2*mu + a3 );
}

首先我得不到的是参数。我有4分和0到1之间的值。那么我的回报值是多少?或者更好的是什么?是y0 ... y3只是点或点的y值,如y0 [0]是x,y0 [1]是y?我需要的是一个算法,它有一些点和一个x值作为参数,返回值应该是y值。

类似的东西:

function calculateCubic( points ){
  var pointsToDraw = [];

  getValue(p1,p2,p3,p4,xCoordinate){
    var yCoordinate;
    yCoordinate = ...
    ...
    return yCoordinate;
  }

  for(var i = 0; i<p.length-3;i++){

    var stepLen = ( p[i+1][0] - p[i][0] ) / 100;
    for( var s = p[i][0]; s <= p[i+1][0] ;s += stepLen ){
        pointsToDraw[pointsToDraw.length] = getValue(p[i],p[i+1],p[i+2],p[i+3],p[i][0]);
    }
  }

  return pointsToDraw;
}

任何人都可以帮助我理解代码snipets并将它们用于我的问题吗?

感谢您的建议!

3 个答案:

答案 0 :(得分:2)

您发布的链接中的示例代码都是来自4个点或2个点和2个导数的三次插值。

&#39; mu&#39;是您要评估y值的参数。输入y0,y1,y2和y3是4个输入点的y坐标。你可以这样做来评估参数&#39; mu&#39;通过将x0,x1,x2和x3传递给函数。

你说你想要一个将x值作为参数输入并将y值作为输出返回的函数。只有当您以显式形式表示曲线时才可以这样做,即y = f(x)。但是,显式形式不能表示具有相同x值的多个y值的曲线。因此,它们不是表示曲线的好方法。参数形式是表示曲线的更好方法。例如,2D曲线C(t)表示为C(t)=(x(t),y(t))或3D曲线可表示为C(t)=(x(t),y( t),z(t))。将整圆表示为(x(t),y(t))=(r cos(t),r sin(t))是参数形式的一个很好的例子。

如果要绘制连接一系列数据点的平滑曲线,最简单的方法是实现Catmull Rom样条曲线或Overhauser样条曲线。它们都是立方Hermite曲线的特殊形式。阅读关于立方Hermite曲线here的维基百科页面,并转到同一页面内的Catmull Rom样条曲线部分,您将能够知道如何创建Catmull Rom样条曲线,插入数据点以及如何评估它以获得(x,y)用于在画布中绘制样条线的值。

答案 1 :(得分:1)

mu是给出曲线位置的参数。要在曲线上绘制一组10个点,请使用相同的y0,y1,y2,y3值和mu 0,0.1,0.2,0.3,... 1.0的值。

要理解这里的y值,看看当我们将mu = 0和mu = 1放入函数时会发生什么。当mu = 0时,函数返回y1。当mu = 1时,函数返回y2。我们看到这种样条曲线穿过中间的两个控制点。

正如Mark所说,这不是最容易使用的样条曲线。你最好使用bezier样条曲线。关于它们的一个非常好的页面是http://pomax.github.io/bezierinfo/。 javascript画布中还有一个bezierCurveTo函数,使它们易于使用API doc

答案 2 :(得分:0)

看起来代码对一组数据点进行了三次插值,返回的是一个Catmull-Rom样条曲线。

使用Bezier样条曲线可能会更好,我认为它实现起来要简单得多。