You can use cubic splines to create cubic segments between each pair of points. The spline will ensure that you hit all the points and the continuity between the segments is higher than 0. A continuity of 0 implies that lines are used to connect the points. Below is an implementation of a Catmull-Rom spline which is one of the simplest/coolest splines out there.
Caveat
This implementation assumes x is monotonically increasing
import java.util.Arrays;
public class CatmullRomSpline
{
protected double[] _x;
protected double[] _y;
public CatmullRomSpline(final double[] x, final double[] y)
{
this._x = x;
this._y = y;
}
public double getValueAt(double x)
{
int length = this._x.length;
int index = Arrays.binarySearch(this._x, x);
double result;
// Exact match was found
if(index >= 0)
{
result = this._y[index];
}
// x is smaller than the smaller value in the sequence
else if(index == -1)
{
result = -1;
}
// x is larger than the largest number in the sequence
else if(index == -length - 1)
{
result = -2;
}
// the number is between two of the numbers in the sequence
else
{
index = -(index + 2);
double p0, p1, p2, p3;
if(index == 0)
{
p1 = this._y[0];
p2 = this._y[1];
p3 = this._y[2];
p0 = 2 * p1 - p2;
}
else if(index >= length - 2)
{
p0 = this._y[length - 3];
p1 = this._y[length - 2];
p2 = this._y[length - 1];
p3 = 2 * p2 - p1;
}
else
{
p1 = this._y[index];
p2 = this._y[index + 1];
p3 = this._y[index + 2];
p0 = this._y[index - 1];
}
// Normalize range from [0, 1] to agree with the derivation of the spline
x = (x - this._x[index]) / (this._x[index + 1] - this._x[index]);
double c0 = p1;
double c1 = p2 - p0;
double c2 = p2 - p1;
double c3 = p1 - p3;
double c4 = c1 - c3;
result = c0 + x * (0.5 * c1 + x * (0.5 * c3 + 3 * c2 - c1 + x * (0.5 * c4 - 2 * c2)));
}
return result;
}
public static void main(String[] args)
{
// I'm fitting a parabola from t = 1 to t = 4
double[] t = new double[] {0, 1, 2, 3, 4, 5};
double[] y = new double[] {0, 1, 4, 9, 16, 25};
int noPoints = 6;
double[] tHat = linspace(1.0, 4.0, noPoints);
CatmullRomSpline csp = new CatmullRomSpline(t, y);
for(double value : tHat)
{
System.out.printf("y(t = %.4f) = %.4f\n", value, csp.getValueAt(value));
}
/* Output
y(t = 1.0000) = 1.0000
y(t = 1.5000) = 2.2500
y(t = 2.0000) = 4.0000
y(t = 2.5000) = 6.2500
y(t = 3.0000) = 9.0000
y(t = 3.5000) = 12.2500
y(t = 4.0000) = 16.0000
*/
}
public static double[] linspace(double begin, double end, int noPoints)
{
double[] arr = new double[noPoints + 1];
double delta = (end - begin) / noPoints;
for(int i = 0; i < noPoints; i++)
{
arr[i] = begin + i * delta;
}
arr[noPoints] = end;
return arr;
}
}