Home | History | Annotate | Download | only in filters
      1 package com.android.gallery3d.filtershow.filters;
      2 
      3 
      4 public class SplineMath {
      5     double[][] mPoints = new double[6][2];
      6     double[] mDerivatives;
      7     SplineMath(int n) {
      8         mPoints = new double[n][2];
      9     }
     10 
     11     public void setPoint(int index, double x, double y) {
     12         mPoints[index][0] = x;
     13         mPoints[index][1] = y;
     14         mDerivatives = null;
     15     }
     16 
     17     public float[][] calculatetCurve(int n) {
     18         float[][] curve = new float[n][2];
     19         double[][] points = new double[mPoints.length][2];
     20         for (int i = 0; i < mPoints.length; i++) {
     21 
     22             points[i][0] = mPoints[i][0];
     23             points[i][1] = mPoints[i][1];
     24 
     25         }
     26         double[] derivatives = solveSystem(points);
     27         float start = (float) points[0][0];
     28         float end = (float) (points[points.length - 1][0]);
     29 
     30         curve[0][0] = (float) (points[0][0]);
     31         curve[0][1] = (float) (points[0][1]);
     32         int last = curve.length - 1;
     33         curve[last][0] = (float) (points[points.length - 1][0]);
     34         curve[last][1] = (float) (points[points.length - 1][1]);
     35 
     36         for (int i = 0; i < curve.length; i++) {
     37 
     38             double[] cur = null;
     39             double[] next = null;
     40             double x = start + i * (end - start) / (curve.length - 1);
     41             int pivot = 0;
     42             for (int j = 0; j < points.length - 1; j++) {
     43                 if (x >= points[j][0] && x <= points[j + 1][0]) {
     44                     pivot = j;
     45                 }
     46             }
     47             cur = points[pivot];
     48             next = points[pivot + 1];
     49             if (x <= next[0]) {
     50                 double x1 = cur[0];
     51                 double x2 = next[0];
     52                 double y1 = cur[1];
     53                 double y2 = next[1];
     54 
     55                 // Use the second derivatives to apply the cubic spline
     56                 // equation:
     57                 double delta = (x2 - x1);
     58                 double delta2 = delta * delta;
     59                 double b = (x - x1) / delta;
     60                 double a = 1 - b;
     61                 double ta = a * y1;
     62                 double tb = b * y2;
     63                 double tc = (a * a * a - a) * derivatives[pivot];
     64                 double td = (b * b * b - b) * derivatives[pivot + 1];
     65                 double y = ta + tb + (delta2 / 6) * (tc + td);
     66 
     67                 curve[i][0] = (float) (x);
     68                 curve[i][1] = (float) (y);
     69             } else {
     70                 curve[i][0] = (float) (next[0]);
     71                 curve[i][1] = (float) (next[1]);
     72             }
     73         }
     74         return curve;
     75     }
     76 
     77     public double getValue(double x) {
     78         double[] cur = null;
     79         double[] next = null;
     80         if (mDerivatives == null)
     81             mDerivatives = solveSystem(mPoints);
     82         int pivot = 0;
     83         for (int j = 0; j < mPoints.length - 1; j++) {
     84             pivot = j;
     85             if (x <= mPoints[j][0]) {
     86                 break;
     87             }
     88         }
     89         cur = mPoints[pivot];
     90         next = mPoints[pivot + 1];
     91         double x1 = cur[0];
     92         double x2 = next[0];
     93         double y1 = cur[1];
     94         double y2 = next[1];
     95 
     96         // Use the second derivatives to apply the cubic spline
     97         // equation:
     98         double delta = (x2 - x1);
     99         double delta2 = delta * delta;
    100         double b = (x - x1) / delta;
    101         double a = 1 - b;
    102         double ta = a * y1;
    103         double tb = b * y2;
    104         double tc = (a * a * a - a) * mDerivatives[pivot];
    105         double td = (b * b * b - b) * mDerivatives[pivot + 1];
    106         double y = ta + tb + (delta2 / 6) * (tc + td);
    107 
    108         return y;
    109 
    110     }
    111 
    112     double[] solveSystem(double[][] points) {
    113         int n = points.length;
    114         double[][] system = new double[n][3];
    115         double[] result = new double[n]; // d
    116         double[] solution = new double[n]; // returned coefficients
    117         system[0][1] = 1;
    118         system[n - 1][1] = 1;
    119         double d6 = 1.0 / 6.0;
    120         double d3 = 1.0 / 3.0;
    121 
    122         // let's create a tridiagonal matrix representing the
    123         // system, and apply the TDMA algorithm to solve it
    124         // (see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm)
    125         for (int i = 1; i < n - 1; i++) {
    126             double deltaPrevX = points[i][0] - points[i - 1][0];
    127             double deltaX = points[i + 1][0] - points[i - 1][0];
    128             double deltaNextX = points[i + 1][0] - points[i][0];
    129             double deltaNextY = points[i + 1][1] - points[i][1];
    130             double deltaPrevY = points[i][1] - points[i - 1][1];
    131             system[i][0] = d6 * deltaPrevX; // a_i
    132             system[i][1] = d3 * deltaX; // b_i
    133             system[i][2] = d6 * deltaNextX; // c_i
    134             result[i] = (deltaNextY / deltaNextX) - (deltaPrevY / deltaPrevX); // d_i
    135         }
    136 
    137         // Forward sweep
    138         for (int i = 1; i < n; i++) {
    139             // m = a_i/b_i-1
    140             double m = system[i][0] / system[i - 1][1];
    141             // b_i = b_i - m(c_i-1)
    142             system[i][1] = system[i][1] - m * system[i - 1][2];
    143             // d_i = d_i - m(d_i-1)
    144             result[i] = result[i] - m * result[i - 1];
    145         }
    146 
    147         // Back substitution
    148         solution[n - 1] = result[n - 1] / system[n - 1][1];
    149         for (int i = n - 2; i >= 0; --i) {
    150             solution[i] = (result[i] - system[i][2] * solution[i + 1]) / system[i][1];
    151         }
    152         return solution;
    153     }
    154 
    155     public static void main(String[] args) {
    156         SplineMath s = new SplineMath(10);
    157         for (int i = 0; i < 10; i++) {
    158             s.setPoint(i, i, i);
    159         }
    160         float[][] curve = s.calculatetCurve(40);
    161 
    162         for (int j = 0; j < curve.length; j++) {
    163             System.out.println(curve[j][0] + "," + curve[j][1]);
    164         }
    165     }
    166 }
    167