2011-12-19 5 views
6

Я пытаюсь нарисовать график, используя Cubic Hermite Splines. Я взял простой код, чтобы сделать это с этой страницы interpolation methods.Cubic Hermite Spline ведет себя странно

Вот мой код:

private float HermiteInterpolate(float y0, float y1, float y2, float y3, float mu) 
{ 
    var mu2 = mu * mu; 

    var a0 = -0.5f * y0 + 1.5f * y1 - 1.5f * y2 + 0.5f * y3; 
    var a1 = y0 - 2.5f * y1 + 2f * y2 - 0.5f * y3; 
    var a2 = -0.5f * y0 + 0.5f * y2; 
    var a3 = y1; 

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

С этими данными (Y-значений, от 0-1, х-значения распределены равномерно от 0-21):

0, 0.09448819, 0.1102362, 0.1338583, 0.1811024, 0.2283465 ,0.3543307, 0.4645669, 0.480315, 0.480315, 0.527559, 0.527559, 0.527559, 0.527559, 0.527559, 0.527559, 0.6062992, 0.6377953, 0.6377953, 0.6377953, 0.7480315

И вот результат:

Hermite Graph

Проблема в том, что на некоторых участках графика линия идет вниз. Глядя на данные, он никогда не уменьшается. Я не знаю, должен ли алгоритм делать это, но для того, над чем я работаю, я хочу, чтобы линии никогда не спускались вниз (и если бы я рисовал график вручную, я бы никогда не делал их направленными вниз) ,

Так,

  • Есть ли что-то не так с графиками?
  • Предполагается ли, что этот алгоритм? Если да, то там, где этого не происходит?
  • Я пробовал косинус интерполяцию, но мне не понравилось, как это получилось.

Вот фактическая функция изображая:

public void DrawGraph(IList<float> items) 
{ 
    for (var x = 0; x < Width; x++) 
    { 
     var percentThrough = (float)x/(float)Width; 
     var itemIndexRaw = items.Count * percentThrough; 
     var itemIndex = (int)Math.Floor(itemIndexRaw); 

     var item = items[itemIndex]; 
     var previousItem = (itemIndex - 1) < 0 ? item : items[itemIndex - 1]; 
     var nextItem = (itemIndex + 1) >= items.Count ? item : items[itemIndex + 1]; 
     var nextNextItem = (itemIndex + 2) >= items.Count ? nextItem : items[itemIndex + 2]; 

     var itemMu = FractionalPart(itemIndexRaw); 

     var pointValue = HermiteInterpolate(previousItem, item, nextItem, nextNextItem, itemMu); 

     WritePixel(x, (int)(pointValue * Height) - 1, (1 - FractionalPart(pointValue)), false); 
     WritePixel(x, (int)(pointValue * Height), 1.0f, false); 
     WritePixel(x, (int)(pointValue * Height) + 1, FractionalPart(pointValue), false); 
    } 
} 
+0

Hi Snea, я пытаюсь понять, как работает Cubic Hermite Spline. Не могли бы вы рассказать мне, как вы называете свой метод HermiteInterpolate? – Doro

ответ

10

Такое поведение является нормальным.

Методы интерполяции накладывают определенные условия непрерывности, чтобы обеспечить появление гладкой кривой. Для интерполяции Эрмита нет условия, чтобы интерполяционная кривая через последовательность возрастающих значений также возрастала повсюду, и поэтому иногда вы получаете эффект, который вы показываете здесь.

Есть что-то под названием monotone cubic interpolation, которое делает то, что вы хотите: если точки данных увеличиваются, то также будет возрастать и интерполяционная кривая.

+1

Отлично! Теперь я просто должен понять, как интерпретировать все эти шаги как код. – Snea

 Смежные вопросы

  • Нет связанных вопросов^_^