KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jrobin > graph > CubicSplineInterpolator


1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info: http://www.jrobin.org
6  * Project Lead: Sasa Markovic (saxon@jrobin.org)
7  *
8  * Developers: Sasa Markovic (saxon@jrobin.org)
9  * Arne Vandamme (cobralord@jrobin.org)
10  *
11  * (C) Copyright 2003, by Sasa Markovic.
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25 package org.jrobin.graph;
26
27 import org.jrobin.core.RrdException;
28 import org.jrobin.core.Util;
29
30 import java.util.Date JavaDoc;
31 import java.util.GregorianCalendar JavaDoc;
32
33 /**
34  * Class used to interpolate datasource values from the collection of (timestamp, values)
35  * points using natural cubic spline interpolation.<p>
36  *
37  * <b>WARNING</b>: So far, this class cannot handle NaN datasource values
38  * (an exception will be thrown by the constructor). Future releases might change this.
39  *
40  * Pass instances of this class to {@link RrdGraphDef#datasource(String, Plottable)
41  * RrdGraphDef.datasource()} to provide spline-interpolated datasource values to JRobin grapher.<p>
42  */

43 public class CubicSplineInterpolator extends Plottable {
44     private double[] x;
45     private double[] y;
46
47     // second derivates come here
48
private double[] y2;
49
50     // internal spline variables
51
private int n, klo, khi;
52
53     /**
54      * Creates cubic spline interpolator from arrays of timestamps and corresponding
55      * datasource values.
56      * @param timestamps timestamps in seconds
57      * @param values corresponding datasource values
58      * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
59      * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
60      */

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     /**
72      * Creates cubic spline interpolator from arrays of Date objects and corresponding
73      * datasource values.
74      * @param dates Array of Date objects
75      * @param values corresponding datasource values
76      * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
77      * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
78      */

79     public CubicSplineInterpolator(Date JavaDoc[] 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     /**
90      * Creates cubic spline interpolator from arrays of GregorianCalendar objects and corresponding
91      * datasource values.
92      * @param dates Array of GregorianCalendar objects
93      * @param values corresponding datasource values
94      * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
95      * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
96      */

97     public CubicSplineInterpolator(GregorianCalendar JavaDoc[] 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     /**
108      * Creates cubic spline interpolator for an array of 2D-points.
109      * @param x x-axis point coordinates
110      * @param y y-axis point coordinates
111      * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
112      * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
113      */

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; // natural spline
142
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         // prepare everything for getValue()
153
klo = 0;
154         khi = n - 1;
155     }
156
157     /**
158      * Calculates spline-interpolated y-value for the corresponding x-value. Call
159      * this if you need spline-interpolated values in your code.
160      * @param xval x-value
161      * @return inteprolated y-value
162      */

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             // out of bounds
169
klo = 0;
170             khi = n - 1;
171         }
172         while (khi - klo > 1) {
173             // find bounding interval using bisection method
174
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     /**
190      * Method overriden from the base class. This method will be called by the framework. Call
191      * this method only if you need spline-interpolated values in your code.
192      * @param timestamp timestamp in seconds
193      * @return inteprolated datasource value
194      */

195     public double getValue(long timestamp) {
196         return getValue((double)timestamp);
197     }
198
199 }
200
Popular Tags