2011-12-19 11 views
6

Sto tentando di disegnare un grafico utilizzando Cubic Hermite Splines. Ho afferrato il semplice codice per farlo da questa pagina interpolation methods.Cubic Hermite Spline si comporta in modo strano

Ecco il mio codice:

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 questi dati (valori y, 0-1, valori x sono distribuiti in modo uniforme 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

ed ecco il risultato:

Hermite Graph

Il problema è che, in alcune aree del grafico, la linea va verso il basso. Guardando i dati, non diminuisce mai. Non so se l'algoritmo dovrebbe fare questo, ma per quello a cui sto lavorando, voglio che le linee non vadano mai verso il basso (e se disegnassi il grafico a mano, non lo farei mai puntare verso il basso in ogni caso) .

Quindi,

  • C'è qualcosa di sbagliato con la grafica?
  • L'algoritmo dovrebbe eseguire questa operazione? Se è così, c'è uno dove questo non accade?
  • Ho provato l'interpolazione del coseno, ma non mi è piaciuto come si è scoperto.

Qui è la rappresentazione grafica delle funzioni attuale:

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

Ciao Snea, sto cercando di capire come funziona Cubic Hermite Spline. Potresti dirmi come chiami il tuo metodo HermiteInterpolate? – Doro

risposta

10

Questo comportamento è normale.

I metodi di interpolazione impongono determinate condizioni di continuità per conferire l'aspetto di una curva uniforme. Per l'interpolazione dell'Hermite, non vi è alcuna condizione che la curva interpolatrice attraverso una sequenza di valori crescenti debba anche aumentare ovunque, e quindi a volte ottieni l'effetto che mostri qui.

C'è qualcosa chiamato monotone cubic interpolation che fa quello che vuoi: se i punti di dati aumentano, anche la curva di interpolazione aumenterà ovunque.

+1

Eccellente! Ora devo solo capire di interpretare tutti quei passaggi come codice. – Snea

Problemi correlati