I'm attempting to draw a graph using Cubic Hermite Splines. I grabbed the simple code to do so from this interpolation methods page.
Here is my code:
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;
}
With this data (y-values, from 0-1, x-values are distributed evenly from 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
And here is the result:
The problem is, at some areas of the graph, the line goes downward. Looking at the data, it never decreases. I don't know if the algorithm is supposed to do this, but for what I am working on, I want the lines to never go downward (and if I was drawing the graph by hand, I would never make them point downward anyway).
So,
Here is the actual graphing function:
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);
}
}
This behavior is normal.
Interpolation methods impose certain continuity conditions in order to give the appearance of a smooth curve. For Hermite interpolation, there is no condition that the interpolating curve through a sequence of increasing values must also be increasing everywhere, and so sometimes you get the effect you show here.
There is something called monotone cubic interpolation which does what you want: if the data points are increasing, the interpolating curve will be increasing everywhere also.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With