2011-12-19 10 views
6

Estoy intentando dibujar un gráfico usando Cubic Hermite Splines. Agarré el código simple para hacerlo desde esta página interpolation methods.cúbico Hermite Spline se comporta de manera extraña

Aquí está mi código:

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

Con estos datos (valores de y, a partir de 0-1, valores x se distribuyen uniformemente desde 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

y aquí está el resultado:

Hermite Graph

El problema es que, en algunas áreas del gráfico, la línea va hacia abajo. Al mirar los datos, nunca disminuye. No sé si se supone que el algoritmo debe hacer esto, pero para lo que estoy trabajando, quiero que las líneas nunca vayan hacia abajo (y si dibujara el gráfico a mano, nunca haría que apuntaran hacia abajo de todos modos) .

Así,

  • ¿Hay algo malo con la gráfica?
  • ¿Se supone que el algoritmo debe hacer esto? Si es así, ¿hay alguno donde esto no ocurra?
  • He intentado la interpolación de coseno, pero no me gustó cómo resultó.

Aquí es la representación gráfica de funciones reales:

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

Hola Snea, estoy tratando de entender cómo funciona Hermetic spline cúbico. ¿Podría decirme cómo llama a su método HermiteInterpolate? – Doro

Respuesta

10

Este comportamiento es normal.

Los métodos de interpolación imponen ciertas condiciones de continuidad para dar la apariencia de una curva suave. Para la interpolación de Hermite, no hay ninguna condición de que la curva de interpolación a través de una secuencia de valores crecientes también deba estar aumentando en todas partes, y así a veces se obtiene el efecto que se muestra aquí.

Hay algo llamado monotone cubic interpolation que hace lo que quiere: si los puntos de datos están aumentando, la curva de interpolación también aumentará en todas partes.

+1

¡Excelente! Ahora solo tengo que descifrar para interpretar todos esos pasos como código. – Snea

Cuestiones relacionadas