moving to core/
[debian/openrocket] / core / src / net / sf / openrocket / util / LinearInterpolator.java
1 package net.sf.openrocket.util;
2
3 import java.util.Iterator;
4 import java.util.Map;
5 import java.util.TreeMap;
6
7 public class LinearInterpolator implements Cloneable {
8
9         private TreeMap<Double, Double> sortMap = new TreeMap<Double,Double>();
10
11         /**
12          * Construct a <code>LinearInterpolator</code> with no points.  Some points must be
13          * added using {@link #addPoints(double[], double[])} before using the interpolator.
14          */
15         public LinearInterpolator() {
16         }
17         
18         /**
19          * Construct a <code>LinearInterpolator</code> with the given points.
20          * 
21          * @param x             the x-coordinates of the points.
22          * @param y             the y-coordinates of the points.
23          * @throws IllegalArgumentException             if the lengths of <code>x</code> and <code>y</code>
24          *                                                                              are not equal.
25          * @see #addPoints(double[], double[])
26          */
27         public LinearInterpolator(double[] x, double[] y) {
28                 addPoints(x,y);
29         }
30         
31         
32         /**
33          * Add the point to the linear interpolation.
34          * 
35          * @param x             the x-coordinate of the point.
36          * @param y             the y-coordinate of the point.
37          */
38         public void addPoint(double x, double y) {
39                 sortMap.put(x, y);
40         }
41         
42         /**
43          * Add the points to the linear interpolation.
44          * 
45          * @param x             the x-coordinates of the points.
46          * @param y             the y-coordinates of the points.
47          * @throws IllegalArgumentException             if the lengths of <code>x</code> and <code>y</code>
48          *                                                                              are not equal.
49          */
50         public void addPoints(double[] x, double[] y) {
51                 if (x.length != y.length) {
52                         throw new IllegalArgumentException("Array lengths do not match, x="+x.length +
53                                         " y="+y.length);
54                 }
55                 for (int i=0; i < x.length; i++) {
56                         sortMap.put(x[i],y[i]);
57                 }
58         }
59         
60         
61         
62         public double getValue(double x) {
63                 Map.Entry<Double,Double> e1, e2;
64                 double x1, x2;
65                 double y1, y2;
66                 
67                 e1 = sortMap.floorEntry(x);
68                 
69                 if (e1 == null) {
70                         // x smaller than any value in the set
71                         e1 = sortMap.firstEntry();
72                         if (e1 == null) {
73                                 throw new IllegalStateException("No points added yet to the interpolator.");
74                         }
75                         return e1.getValue();
76                 }
77                 
78                 x1 = e1.getKey();
79                 e2 = sortMap.higherEntry(x1);
80
81                 if (e2 == null) {
82                         // x larger than any value in the set
83                         return e1.getValue();
84                 }
85                 
86                 x2 = e2.getKey();
87                 y1 = e1.getValue();
88                 y2 = e2.getValue();
89                 
90                 return (x - x1)/(x2-x1) * (y2-y1) + y1;
91         }
92         
93         
94         public double[] getXPoints() {
95                 double[] x = new double[sortMap.size()];
96                 Iterator<Double> iter = sortMap.keySet().iterator();
97                 for (int i=0; iter.hasNext(); i++) {
98                         x[i] = iter.next();
99                 }
100                 return x;
101         }
102         
103         
104         @SuppressWarnings("unchecked")
105         @Override
106         public LinearInterpolator clone() {
107                 try {
108                         LinearInterpolator other = (LinearInterpolator)super.clone();
109                         other.sortMap = (TreeMap<Double,Double>)this.sortMap.clone();
110                         return other;
111                 } catch (CloneNotSupportedException e) {
112                         throw new BugException("CloneNotSupportedException?!",e);
113                 }
114         }
115
116         
117         public static void main(String[] args) {
118                 LinearInterpolator interpolator = new LinearInterpolator(
119                                 new double[] {1, 1.5, 2, 4, 5},
120                                 new double[] {0, 1,   0, 2, 2}
121                 );
122                 
123                 for (double x=0; x < 6; x+=0.1) {
124                         System.out.printf("%.1f:  %.2f\n", x, interpolator.getValue(x));
125                 }
126         }
127         
128 }