1 25 package org.jrobin.graph; 26 27 import org.jrobin.core.RrdException; 28 import org.jrobin.core.Util; 29 30 import java.util.Date ; 31 import java.util.GregorianCalendar ; 32 33 43 public class CubicSplineInterpolator extends Plottable { 44 private double[] x; 45 private double[] y; 46 47 private double[] y2; 49 50 private int n, klo, khi; 52 53 61 public CubicSplineInterpolator(long[] timestamps, double[] values) throws RrdException { 62 this.x = new double[timestamps.length]; 63 for(int i = 0; i < timestamps.length; i++) { 64 this.x[i] = timestamps[i]; 65 } 66 this.y = values; 67 validate(); 68 spline(); 69 } 70 71 79 public CubicSplineInterpolator(Date [] dates, double[] values) throws RrdException { 80 this.x = new double[dates.length]; 81 for(int i = 0; i < dates.length; i++) { 82 this.x[i] = Util.getTimestamp(dates[i]); 83 } 84 this.y = values; 85 validate(); 86 spline(); 87 } 88 89 97 public CubicSplineInterpolator(GregorianCalendar [] dates, double[] values) throws RrdException { 98 this.x = new double[dates.length]; 99 for(int i = 0; i < dates.length; i++) { 100 this.x[i] = Util.getTimestamp(dates[i]); 101 } 102 this.y = values; 103 validate(); 104 spline(); 105 } 106 107 114 public CubicSplineInterpolator(double[] x, double[] y) throws RrdException { 115 this.x = x; 116 this.y = y; 117 validate(); 118 spline(); 119 } 120 121 private void validate() throws RrdException { 122 boolean ok = true; 123 if(x.length != y.length || x.length < 3) { 124 ok = false; 125 } 126 for(int i = 0; i < x.length - 1 && ok; i++) { 127 if(x[i] >= x[i + 1] || Double.isNaN(y[i])) { 128 ok = false; 129 } 130 } 131 if(!ok) { 132 throw new RrdException("Invalid plottable data supplied"); 133 } 134 } 135 136 private void spline() { 137 n = x.length; 138 y2 = new double[n]; 139 double[] u = new double[n - 1]; 140 y2[0] = y2[n - 1] = 0.0; 141 u[0] = 0.0; for (int i = 1; i <= n - 2; i++) { 143 double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]); 144 double p = sig * y2[i - 1] + 2.0; 145 y2[i] = (sig - 1.0) / p; 146 u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]); 147 u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p; 148 } 149 for (int k = n - 2; k >= 0; k--) { 150 y2[k] = y2[k] * y2[k + 1] + u[k]; 151 } 152 klo = 0; 154 khi = n - 1; 155 } 156 157 163 public double getValue(double xval) { 164 if(xval < x[0] || xval > x[n - 1]) { 165 return Double.NaN; 166 } 167 if(xval < x[klo] || xval > x[khi]) { 168 klo = 0; 170 khi = n - 1; 171 } 172 while (khi - klo > 1) { 173 int k = (khi + klo) / 2; 175 if (x[k] > xval) { 176 khi = k; 177 } 178 else { 179 klo = k; 180 } 181 } 182 double h = x[khi] - x[klo]; 183 double a = (x[khi] - xval) / h; 184 double b = (xval - x[klo]) / h; 185 return a * y[klo] + b * y[khi] + 186 ((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * (h * h) / 6.0; 187 } 188 189 195 public double getValue(long timestamp) { 196 return getValue((double)timestamp); 197 } 198 199 } 200 | Popular Tags |