Interpolation over an array (or two)

27,385

Solution 1

The other answers give you linear interpolations -- these don't really work for complex, nonlinear data. You want a spline fit, (spline interpolation) I believe.

Spline fits describe regions of the data using a set of control points from the data, then apply a polynomial interpolation between control points. More control points gives you a more accurate fit, less a more general fit. Splines are much more accurate than linear fits, faster to use than a general regression fit, better than a high-order polynomial because it won't do crazy things between control points.

I can't remember names off the top of my head, but there are some excellent fitting libraries in Java -- I suggest you look for one rather than writing your own function.


**EDIT: Libraries that might be useful: **

** Theory/code that may be useful: **

  • Spline applets with code: link
  • Arkan spline fitting for poly-lines to bezier splines
  • Theory of splines, and some math for fitting. More math, less code, might help if the libraries don't.

Solution 2

Designed for ONE Dimension data array

import java.util.ArrayList;

public class Interpolator {

public static Float CosineInterpolate(Float y1,Float y2,Float mu)
{
    double mu2;

    mu2 = (1.0f-Math.cos(mu*Math.PI))/2.0f;
    Float f_mu2 = new Float(mu2);
    return(y1*(1.0f-f_mu2)+y2*f_mu2);
}

public static Float LinearInterpolate(Float y1,Float y2,Float mu)
{
    return(y1*(1-mu)+y2*mu);
}


public static Float[] Interpolate(Float[] a, String mode) {

    // Check that have at least the very first and very last values non-null
    if (!(a[0] != null && a[a.length-1] != null)) return null;

    ArrayList<Integer> non_null_idx = new ArrayList<Integer>();
    ArrayList<Integer> steps = new ArrayList<Integer>();

    int step_cnt = 0;
    for (int i=0; i<a.length; i++)
    {
        if (a[i] != null)
        {
            non_null_idx.add(i);
            if (step_cnt != 0) {
                steps.add(step_cnt);
                System.err.println("aDDed step >> " + step_cnt);
            }
            step_cnt = 0;
        }
        else
        {
            step_cnt++;
        }
    }

    Float f_start = null;
    Float f_end = null;
    Float f_step = null;
    Float f_mu = null;

    int i = 0;
    while (i < a.length - 1) // Don't do anything for the very last element (which should never be null)
    {
        if (a[i] != null && non_null_idx.size() > 1 && steps.size() > 0)
        {
            f_start = a[non_null_idx.get(0)];
            f_end = a[non_null_idx.get(1)];
            f_step = new Float(1.0) / new Float(steps.get(0) + 1);
            f_mu = f_step;
            non_null_idx.remove(0);
            steps.remove(0);
        }
        else if (a[i] == null)
        {
            if (mode.equalsIgnoreCase("cosine"))
                a[i] = CosineInterpolate(f_start, f_end, f_mu);
            else
                a[i] = LinearInterpolate(f_start, f_end, f_mu);
            f_mu += f_step;
        }
        i++;
    }

    return a;
}
}

Don't know if it helps... It is very fast coded, so if anyone has a nicer / more performing way to do the same, thank for contributing.

USAGE:

input : Float[] a = {1.0f, null, null, 2.0f, null, null, null, 15.0f};

call : Interpolator.Interpolate(a, "Linear");

output : 1.0|1.3333333|1.6666667|2.0|5.25|8.5|11.75|15.0

Solution 3

I know this is an old answer, but it's the first google hit when searching for Java interpolation. The accepted answer provides some helpful links, but JMSL must be purchased, and the JSpline+ website looks sketchy.

Apache Commons Math has implementations of linear and spline interpolations that appear simple, functional, and trustworthy.

http://commons.apache.org/proper/commons-math/

Solution 4

Simple linear interpolation can be calculated using something like:

Point2D interp1_lin(Point2D p1, Point2D p2, double x) {
 //Pre conditions
assert p1.x<x;
assert x<p2.x;
//Calculate slope from p1 to p2
double m = (p2.x-p1.x)/(p2.y-p1.y);
//Calculate y position of x
double y = (x-p1.x)*m+p1.y;
//create new point
return new Point2D.Double(x,y);
}

Does this help?

Share:
27,385
Robert
Author by

Robert

Updated on March 13, 2020

Comments

  • Robert
    Robert about 4 years

    I'm looking for a java library or some help to write my own interpolation function. That is I have two arrays of doubles which are potentially different sizes, but are ordered. I need to be able to make an estimate of intermediate values, and insert so that both arrays become the same size. In fact the total number of points appearing in the interpolation is the sum of the 2 array sizes minus 1. The range of each array must stay the same however, so there is no extrapolation needed.

    eg. a1 = [1, 4, 9, 16, 25, 36] and a2 = [6, 9, 14, 30]

    the results could be eg.

    a1 = [1, 2.25, 4, 6.25, 9, 12.25, 16, 25, 36] and a2 = [6, 6.5625, 7.25, 9, 10.0625, 11.25, 14, 25.25, 30]

    these examples are f(x) = x^2 and g(x) = x^2 + 5, however could easily have been any polynomial - the point is to be able to estimate/approximate the function from the dataset well enough to provide decent enough interpolation. Here the x value is just the index of the input array. In the output only the y values are important.

  • Robert
    Robert almost 15 years
    ok, I didn't think through my example properly - suppose every array index is the x-value for the input- then after interpolation we are no longer interested in the x-value.
  • BobMcGee
    BobMcGee almost 15 years
    I've added links to some libraries, and code + theory to work with splines if the libraries do not. Don't forget to accept the answer if it's helpful to you!
  • Slava
    Slava over 8 years
    There's also special LinerarInterpolator for that purposes.
  • 3xCh1_23
    3xCh1_23 about 7 years
    returns a null.
  • Developer66
    Developer66 almost 3 years
    @3xCh1_23 last value in array must not be null