Hi Jody et al.

Don't know if the code below is useful in this context, but if it is
feel free to use it (suitably hacked).  It's a routine to fit a smooth
curve through a set of points using cubic spline interpolation.  Works
for me but you might want to test it out.

ciao
Michael

/**
 * A utility class for cubic spline interpolation in two dimensions.
 *
 * @author Michael Bedward <[EMAIL PROTECTED]>
 */
public class SplineInterpolator {

    /**
     * Cubic spline interpolation through the set of points with
     * coordinates given by x and y input arrays.
     * <P>
     * Returns the coords of a line interpolated through np points
     * (including the first and last control points) which are
     * approximately evenly-spaced (fudged using linear interp).
     * <P>
     * Adapted from an algorithm in Press et al. 1992
     * "Numeical Recipes in C". Cambridge University Press
     *
     * @param x x-coords of control points
     * @param y y-coords of control points
     * @param np number of interpolation points
     * @return a 2D double array of interpolated point locations with
     * x-xoords in array[0][] and y-coords in array[1][]
     *
     * @throws java.lang.IllegalArgumentException
     */
    public static double[][] interp(double[] x, double[] y, int np)
throws IllegalArgumentException {
        int N = x.length;
        if (N == 0 || N != y.length) {
            throw new IllegalArgumentException("length of input array
must be equal and > 0");
        }
        if (np < N) {
            throw new IllegalArgumentException("np should be larger
than length of input arrays");
        }

        // x values need to be considered in ascending order
        int[] o = getOrder(x);

        // Interpolation (as done below) will fail if any of the input
x coords are equal
        double prec = 1.0e-8;
        for (int i = 1; i < N; i++) {
            if (Math.abs(x[o[i]] - x[o[i - 1]]) < prec) {
                throw new IllegalArgumentException("x values must be distinct");
            }
        }

        // first derivatives
        double[] dy = new double[N];

        // second derivatives
        double[] ddy = new double[N];

        // in this implementation we set the value of the second
derivatives at the end-points
        // to 0 (the so-called natural cublic spline). See Press et
al. 1992 for alternative
        // approaches.
        ddy[0] = ddy[N - 1] = dy[0] = 0.0;

        // 
========================================================================
        // tridiagonal algorithm to calculate the piece-wise splines
        double sig, p;
        for (int i = 1; i < N - 1; i++) {
            sig = (x[o[i]] - x[o[i - 1]]) / (x[o[i + 1]] - x[o[i - 1]]);
            p = sig * ddy[i - 1] + 2.0;
            ddy[i] = (sig - 1.0) / p;
            dy[i] = (y[o[i + 1]] - y[o[i]]) / (x[o[i + 1]] - x[o[i]])
- (y[o[i]] - y[o[i - 1]]) / (x[o[i]] - x[o[i - 1]]);
            dy[i] = (6.0d * dy[i] / (x[o[i + 1]] - x[o[i - 1]]) - sig
* dy[i - 1]) / p;
        }

        for (int i = N - 2; i >= 0; i--) {
            ddy[i] = ddy[i] * ddy[i + 1] + dy[i];
        }

        // 
========================================================================
        // interpolation

        // first find approximate distance along curve by linear interp
        double[] dist = new double[N];
        double[] xdiff = new double[N];
        dist[0] = xdiff[0] = 0.0;
        for (int i = 1; i < N; i++) {
            xdiff[i] = x[o[i]] - x[o[i - 1]];
            double ydiff = y[o[i]] - y[o[i - 1]];
            dist[i] = dist[i - 1] + Math.sqrt(xdiff[i] * xdiff[i] +
ydiff * ydiff);
        }

        // spacing
        double dIncr = dist[N - 1] / (np - 1);

        double[][] xyInterp = new double[2][np];
        xyInterp[0][0] = x[o[0]];
        xyInterp[1][0] = y[o[0]];
        xyInterp[0][np - 1] = x[o[N - 1]];
        xyInterp[1][np - 1] = y[o[N - 1]];

        double curDist = dIncr;
        int k = 1;
        for (int i = 1; i < np - 1; i++, curDist += dIncr) {
            while (curDist > dist[k]) {
                k++;
            }

            // locate the x coord of the interpolated point
            double delta = (curDist - dist[k - 1]) / (dist[k] - dist[k - 1]);
            xyInterp[0][i] = x[o[k - 1]] + delta * xdiff[k];

            // locate the y coord by evaluating the cubic spline polynomial
            double h = x[o[k]] - x[o[k - 1]];
            double a = (x[o[k]] - xyInterp[0][i]) / h;
            double b = (xyInterp[0][i] - x[o[k - 1]]) / h;
            xyInterp[1][i] = a * y[o[k - 1]] + b * y[o[k]] +
                    ((a * a * a - a) * ddy[k - 1] + (b * b * b - b) *
ddy[k]) * (h * h) / 6.0;
        }

        return xyInterp;
    }

    /*
     * Get order of values in the input array.
     */
    private static int[] getOrder(double[] x) {
        if (x.length == 0) {
            return null;
        }

        int[] order = new int[x.length];
        for (int i = 0; i < x.length; i++) {
            order[i] = i;
        }

        // using shellsort algorithm as modified from Sedgewick 1990...
        // Algorithms in C
        //
        int[] incs = new int[]{
            1391376, 463792, 198768, 86961, 33936, 13776,
            4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1
        };

        int i0, j;
        double v;
        for (int k = 0; k < incs.length; k++) {
            for (int h = incs[k], i = h; i < x.length; i++) {
                j = i;
                i0 = order[j];
                v = x[i0];
                while (j > h - 1 && x[order[j - h]] > v) {
                    order[j] = order[j - h];
                    j -= h;
                }
                order[j] = i0;
            }
        }

        return order;
    }
}

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft 
Defy all challenges. Microsoft(R) Visual Studio 2008. 
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Geotools-gt2-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users

Reply via email to