1 25 package org.jrobin.graph; 26 27 import org.jrobin.core.RrdException; 28 import org.jrobin.core.Util; 29 import java.util.Date ; 30 import java.util.GregorianCalendar ; 31 32 45 public class LinearInterpolator extends Plottable { 46 48 public static final int INTERPOLATE_LEFT = 0; 49 51 public static final int INTERPOLATE_RIGHT = 1; 52 54 public static final int INTERPOLATE_LINEAR = 2; 55 57 public static final int INTERPOLATE_REGRESSION = 3; 58 59 private int lastIndexUsed = 0; 60 private int interpolationMethod = INTERPOLATE_LINEAR; 61 62 private long[] timestamps; 63 private double[] values; 64 65 double b0 = Double.NaN, b1 = Double.NaN; 67 68 75 public LinearInterpolator(long[] timestamps, double[] values) throws RrdException { 76 this.timestamps = timestamps; 77 this.values = values; 78 validate(); 79 } 80 81 88 public LinearInterpolator(Date [] dates, double[] values) throws RrdException { 89 this.values = values; 90 timestamps = new long[dates.length]; 91 for(int i = 0; i < dates.length; i++) { 92 timestamps[i] = Util.getTimestamp(dates[i]); 93 } 94 validate(); 95 } 96 97 104 public LinearInterpolator(GregorianCalendar [] dates, double[] values) throws RrdException { 105 this.values = values; 106 timestamps = new long[dates.length]; 107 for(int i = 0; i < dates.length; i++) { 108 timestamps[i] = Util.getTimestamp(dates[i]); 109 } 110 validate(); 111 } 112 113 private void validate() throws RrdException { 114 boolean ok = true; 115 if(timestamps.length != values.length || timestamps.length < 2) { 116 ok = false; 117 } 118 for(int i = 0; i < timestamps.length - 1 && ok; i++) { 119 if(timestamps[i] >= timestamps[i + 1]) { 120 ok = false; 121 } 122 } 123 if(!ok) { 124 throw new RrdException("Invalid plottable data supplied"); 125 } 126 } 127 128 152 public void setInterpolationMethod(int interpolationMethod) { 153 switch(interpolationMethod) { 154 case INTERPOLATE_REGRESSION: 155 calculateBestFitLine(); 156 case INTERPOLATE_LEFT: 157 case INTERPOLATE_RIGHT: 158 case INTERPOLATE_LINEAR: 159 this.interpolationMethod = interpolationMethod; 160 break; 161 default: 162 this.interpolationMethod = INTERPOLATE_LINEAR; 163 } 164 } 165 166 private void calculateBestFitLine() { 167 int count = timestamps.length, validCount = 0; 168 double ts = 0.0, vs = 0.0; 169 for(int i = 0; i < count; i++) { 170 if(!Double.isNaN(values[i])) { 171 ts += timestamps[i]; 172 vs += values[i]; 173 validCount++; 174 } 175 } 176 if(validCount <= 1) { 177 b0 = b1 = Double.NaN; 179 return; 180 } 181 ts /= validCount; 182 vs /= validCount; 183 double s1 = 0, s2 = 0; 184 for(int i = 0; i < count; i++) { 185 if(!Double.isNaN(values[i])) { 186 double dt = timestamps[i] - ts; 187 double dv = values[i] - vs; 188 s1 += dt * dv; 189 s2 += dt * dt; 190 } 191 } 192 b1 = s1 / s2; 193 b0 = vs - b1 * ts; 194 } 195 196 202 public double getValue(long timestamp) { 203 if(interpolationMethod == INTERPOLATE_REGRESSION) { 204 return b0 + b1 * timestamp; 205 } 206 int count = timestamps.length; 207 if(timestamp < timestamps[0] || timestamp > timestamps[count - 1]) { 209 return Double.NaN; 210 } 211 int startIndex = lastIndexUsed; 213 if(timestamp < timestamps[lastIndexUsed]) { 214 startIndex = 0; 216 } 217 for(int i = startIndex; i < count; i++) { 218 if(timestamps[i] == timestamp) { 219 return values[i]; 220 } 221 if(i < count - 1 && timestamps[i] < timestamp && timestamp < timestamps[i + 1]) { 222 lastIndexUsed = i; 224 switch(interpolationMethod) { 225 case INTERPOLATE_LEFT: 226 return values[i]; 227 case INTERPOLATE_RIGHT: 228 return values[i + 1]; 229 case INTERPOLATE_LINEAR: 230 double slope = (values[i + 1] - values[i]) / 231 (timestamps[i + 1] - timestamps[i]); 232 return values[i] + slope * (timestamp - timestamps[i]); 233 default: 234 return Double.NaN; 235 } 236 } 237 } 238 return Double.NaN; 240 } 241 } 242 | Popular Tags |