Fix commit from revision 953 which reverted a bunch of changes related to Froyo compa...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Thu, 9 Aug 2012 15:04:36 +0000 (15:04 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Thu, 9 Aug 2012 15:04:36 +0000 (15:04 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@962 180e2498-e6e9-4542-8430-84ac67f01cd8

core/src/net/sf/openrocket/util/LinearInterpolator.java

index 1631a9de680a1df812f5cf9a9d78dd2a0e6f59d4..e16726bb52e136ca273c59fa6d7dab788e762d67 100644 (file)
@@ -1,9 +1,8 @@
 package net.sf.openrocket.util;
 
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
+import java.util.SortedMap;
 import java.util.TreeMap;
 
 public class LinearInterpolator implements Cloneable {
@@ -16,7 +15,7 @@ public class LinearInterpolator implements Cloneable {
         */
        public LinearInterpolator() {
        }
-       
+
        /**
         * Construct a <code>LinearInterpolator</code> with the given points.
         * 
@@ -29,11 +28,11 @@ public class LinearInterpolator implements Cloneable {
        public LinearInterpolator(double[] x, double[] y) {
                addPoints(x,y);
        }
-       
+
        public LinearInterpolator(List<Double> x, List<Double> y) {
                addPoints(x,y);
        }
-       
+
        /**
         * Add the point to the linear interpolation.
         * 
@@ -43,7 +42,7 @@ public class LinearInterpolator implements Cloneable {
        public void addPoint(double x, double y) {
                sortMap.put(x, y);
        }
-       
+
        /**
         * Add the points to the linear interpolation.
         * 
@@ -61,7 +60,7 @@ public class LinearInterpolator implements Cloneable {
                        sortMap.put(x[i],y[i]);
                }
        }
-       
+
        public void addPoints(List<Double> x, List<Double> y){
                if (x.size() != y.size()) {
                        throw new IllegalArgumentException("Array lengths do not match, x="+x.size() +
@@ -71,40 +70,65 @@ public class LinearInterpolator implements Cloneable {
                        sortMap.put( (Double) x.toArray()[i], (Double) y.toArray()[i]);
                }
        }
-       
-       
+
+
        public double getValue(double x) {
-               Map.Entry<Double,Double> e1, e2;
                double x1, x2;
-               double y1, y2;
+               Double y1, y2;
+               // Froyo does not support floorEntry, firstEntry or higherEntry.  We instead have to
+               // resort to using other more awkward methods.
+
+               y1 = sortMap.get(x);
+
+               if ( y1 != null ) {
+                       // Wow, x was a key in the map.  Such luck.
+                       return y1.doubleValue();
+               }
+
+               // we now know that x is not in the map, so we need to find the lower and higher keys.
                
-               e1 = sortMap.floorEntry(x);
+               // let's just make certain that our map is not empty.
+               if ( sortMap.isEmpty() ) {
+                       throw new IllegalStateException("No points added yet to the interpolator.");
+               }
                
-               if (e1 == null) {
-                       // x smaller than any value in the set
-                       e1 = sortMap.firstEntry();
-                       if (e1 == null) {
-                               throw new IllegalStateException("No points added yet to the interpolator.");
-                       }
-                       return e1.getValue();
+               // firstKey in the map - cannot be null since the map is not empty.
+               Double firstKey = sortMap.firstKey();
+
+               // x is smaller than the first entry in the map.
+               if ( x < firstKey.doubleValue() ) {
+                       y1 = sortMap.get(firstKey);
+                       return y1.doubleValue();
                }
                
-               x1 = e1.getKey();
-               e2 = sortMap.higherEntry(x1);
+               // floor key is the largest key smaller than x - since we have at least one key,
+               // and x>=firstKey, we know that floorKey != null.
+               Double floorKey = sortMap.subMap(firstKey, x).lastKey();
+
+               x1 = floorKey.doubleValue();
+               y1 = sortMap.get(floorKey);
 
-               if (e2 == null) {
-                       // x larger than any value in the set
-                       return e1.getValue();
+               // Now we need to find the key that is greater or equal to x
+               SortedMap<Double,Double> tailMap = sortMap.tailMap(x);
+
+               // Check if x is bigger than all the entries.
+               if ( tailMap.isEmpty() ) {
+                       return y1.doubleValue();
                }
+               Double ceilKey = tailMap.firstKey();
                
-               x2 = e2.getKey();
-               y1 = e1.getValue();
-               y2 = e2.getValue();
+               // Check if x is bigger than all the entries.
+               if ( ceilKey == null ) {
+                       return y1.doubleValue();
+               }
                
+               x2 = ceilKey.doubleValue();
+               y2 = sortMap.get(ceilKey);
+
                return (x - x1)/(x2-x1) * (y2-y1) + y1;
        }
-       
-       
+
+
        public double[] getXPoints() {
                double[] x = new double[sortMap.size()];
                Iterator<Double> iter = sortMap.keySet().iterator();
@@ -113,8 +137,8 @@ public class LinearInterpolator implements Cloneable {
                }
                return x;
        }
-       
-       
+
+
        @SuppressWarnings("unchecked")
        @Override
        public LinearInterpolator clone() {
@@ -127,25 +151,4 @@ public class LinearInterpolator implements Cloneable {
                }
        }
 
-       
-       public static void main(String[] args) {
-               LinearInterpolator interpolator = new LinearInterpolator(
-                               new double[] {1, 1.5, 2, 4, 5},
-                               new double[] {0, 1,   0, 2, 2}
-               );
-               
-               for (double x=0; x < 6; x+=0.1) {
-                       System.out.printf("%.1f:  %.2f\n", x, interpolator.getValue(x));
-               }
-               
-               // Should be the same
-               
-               ArrayList<Double> time = new ArrayList<Double>( Arrays.asList( new Double[] {1.0, 1.5, 2.0, 4.0, 5.0} ));
-               ArrayList<Double> y = new ArrayList<Double>( Arrays.asList( new Double[] {0.0, 1.0, 0.0, 2.0, 2.0} ));
-               
-               LinearInterpolator interpolator2 = new LinearInterpolator(time,y);
-               for (double x=0; x < 6; x+=0.1) {
-                       System.out.printf("%.1f:  %.2f\n", x, interpolator2.getValue(x));
-               }
-       }       
 }