Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / android-libraries / achartengine / src / org / achartengine / util / MathHelper.java
diff --git a/android-libraries/achartengine/src/org/achartengine/util/MathHelper.java b/android-libraries/achartengine/src/org/achartengine/util/MathHelper.java
new file mode 100644 (file)
index 0000000..f5b893b
--- /dev/null
@@ -0,0 +1,174 @@
+/**\r
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL\r
+ *  \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *  \r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *  \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.achartengine.util;\r
+\r
+import java.text.NumberFormat;\r
+import java.text.ParseException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * Utility class for math operations.\r
+ */\r
+public class MathHelper {\r
+  /** A value that is used a null value. */\r
+  public static final double NULL_VALUE = Double.MAX_VALUE;\r
+  /**\r
+   * A number formatter to be used to make sure we have a maximum number of\r
+   * fraction digits in the labels.\r
+   */\r
+  private static final NumberFormat FORMAT = NumberFormat.getNumberInstance();\r
+\r
+  private MathHelper() {\r
+    // empty constructor\r
+  }\r
+\r
+  /**\r
+   * Calculate the minimum and maximum values out of a list of doubles.\r
+   * \r
+   * @param values the input values\r
+   * @return an array with the minimum and maximum values\r
+   */\r
+  public static double[] minmax(List<Double> values) {\r
+    if (values.size() == 0) {\r
+      return new double[2];\r
+    }\r
+    double min = values.get(0);\r
+    double max = min;\r
+    int length = values.size();\r
+    for (int i = 1; i < length; i++) {\r
+      double value = values.get(i);\r
+      min = Math.min(min, value);\r
+      max = Math.max(max, value);\r
+    }\r
+    return new double[] { min, max };\r
+  }\r
+\r
+  /**\r
+   * Computes a reasonable set of labels for a data interval and number of\r
+   * labels.\r
+   * \r
+   * @param start start value\r
+   * @param end final value\r
+   * @param approxNumLabels desired number of labels\r
+   * @return collection containing {start value, end value, increment}\r
+   */\r
+  public static List<Double> getLabels(final double start, final double end,\r
+      final int approxNumLabels) {\r
+    FORMAT.setMaximumFractionDigits(5);\r
+    List<Double> labels = new ArrayList<Double>();\r
+    double[] labelParams = computeLabels(start, end, approxNumLabels);\r
+    // when the start > end the inc will be negative so it will still work\r
+    int numLabels = 1 + (int) ((labelParams[1] - labelParams[0]) / labelParams[2]);\r
+    // we want the range to be inclusive but we don't want to blow up when\r
+    // looping for the case where the min and max are the same. So we loop\r
+    // on\r
+    // numLabels not on the values.\r
+    for (int i = 0; i < numLabels; i++) {\r
+      double z = labelParams[0] + i * labelParams[2];\r
+      try {\r
+        // this way, we avoid a label value like 0.4000000000000000001 instead\r
+        // of 0.4\r
+        z = FORMAT.parse(FORMAT.format(z)).doubleValue();\r
+      } catch (ParseException e) {\r
+        // do nothing here\r
+      }\r
+      labels.add(z);\r
+    }\r
+    return labels;\r
+  }\r
+\r
+  /**\r
+   * Computes a reasonable number of labels for a data range.\r
+   * \r
+   * @param start start value\r
+   * @param end final value\r
+   * @param approxNumLabels desired number of labels\r
+   * @return double[] array containing {start value, end value, increment}\r
+   */\r
+  private static double[] computeLabels(final double start, final double end,\r
+      final int approxNumLabels) {\r
+    if (Math.abs(start - end) < 0.0000001f) {\r
+      return new double[] { start, start, 0 };\r
+    }\r
+    double s = start;\r
+    double e = end;\r
+    boolean switched = false;\r
+    if (s > e) {\r
+      switched = true;\r
+      double tmp = s;\r
+      s = e;\r
+      e = tmp;\r
+    }\r
+    double xStep = roundUp(Math.abs(s - e) / approxNumLabels);\r
+    // Compute x starting point so it is a multiple of xStep.\r
+    double xStart = xStep * Math.ceil(s / xStep);\r
+    double xEnd = xStep * Math.floor(e / xStep);\r
+    if (switched) {\r
+      return new double[] { xEnd, xStart, -1.0 * xStep };\r
+    }\r
+    return new double[] { xStart, xEnd, xStep };\r
+  }\r
+\r
+  /**\r
+   * Given a number, round up to the nearest power of ten times 1, 2, or 5. The\r
+   * argument must be strictly positive.\r
+   */\r
+  private static double roundUp(final double val) {\r
+    int exponent = (int) Math.floor(Math.log10(val));\r
+    double rval = val * Math.pow(10, -exponent);\r
+    if (rval > 5.0) {\r
+      rval = 10.0;\r
+    } else if (rval > 2.0) {\r
+      rval = 5.0;\r
+    } else if (rval > 1.0) {\r
+      rval = 2.0;\r
+    }\r
+    rval *= Math.pow(10, exponent);\r
+    return rval;\r
+  }\r
+\r
+  /**\r
+   * Transforms a list of Float values into an array of float.\r
+   * \r
+   * @param values the list of Float\r
+   * @return the array of floats\r
+   */\r
+  public static float[] getFloats(List<Float> values) {\r
+    int length = values.size();\r
+    float[] result = new float[length];\r
+    for (int i = 0; i < length; i++) {\r
+      result[i] = values.get(i).floatValue();\r
+    }\r
+    return result;\r
+  }\r
+\r
+  /**\r
+   * Transforms a list of Double values into an array of double.\r
+   * \r
+   * @param values the list of Double\r
+   * @return the array of doubles\r
+   */\r
+  public static double[] getDoubles(List<Double> values) {\r
+    int length = values.size();\r
+    double[] result = new double[length];\r
+    for (int i = 0; i < length; i++) {\r
+      result[i] = values.get(i).doubleValue();\r
+    }\r
+    return result;\r
+  }\r
+\r
+}\r