2 * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
16 package org.achartengine.util;
\r
18 import java.text.NumberFormat;
\r
19 import java.text.ParseException;
\r
20 import java.util.ArrayList;
\r
21 import java.util.List;
\r
24 * Utility class for math operations.
\r
26 public class MathHelper {
\r
27 /** A value that is used a null value. */
\r
28 public static final double NULL_VALUE = Double.MAX_VALUE;
\r
30 * A number formatter to be used to make sure we have a maximum number of
\r
31 * fraction digits in the labels.
\r
33 private static final NumberFormat FORMAT = NumberFormat.getNumberInstance();
\r
35 private MathHelper() {
\r
36 // empty constructor
\r
40 * Calculate the minimum and maximum values out of a list of doubles.
\r
42 * @param values the input values
\r
43 * @return an array with the minimum and maximum values
\r
45 public static double[] minmax(List<Double> values) {
\r
46 if (values.size() == 0) {
\r
47 return new double[2];
\r
49 double min = values.get(0);
\r
51 int length = values.size();
\r
52 for (int i = 1; i < length; i++) {
\r
53 double value = values.get(i);
\r
54 min = Math.min(min, value);
\r
55 max = Math.max(max, value);
\r
57 return new double[] { min, max };
\r
61 * Computes a reasonable set of labels for a data interval and number of
\r
64 * @param start start value
\r
65 * @param end final value
\r
66 * @param approxNumLabels desired number of labels
\r
67 * @return collection containing {start value, end value, increment}
\r
69 public static List<Double> getLabels(final double start, final double end,
\r
70 final int approxNumLabels) {
\r
71 FORMAT.setMaximumFractionDigits(5);
\r
72 List<Double> labels = new ArrayList<Double>();
\r
73 double[] labelParams = computeLabels(start, end, approxNumLabels);
\r
74 // when the start > end the inc will be negative so it will still work
\r
75 int numLabels = 1 + (int) ((labelParams[1] - labelParams[0]) / labelParams[2]);
\r
76 // we want the range to be inclusive but we don't want to blow up when
\r
77 // looping for the case where the min and max are the same. So we loop
\r
79 // numLabels not on the values.
\r
80 for (int i = 0; i < numLabels; i++) {
\r
81 double z = labelParams[0] + i * labelParams[2];
\r
83 // this way, we avoid a label value like 0.4000000000000000001 instead
\r
85 z = FORMAT.parse(FORMAT.format(z)).doubleValue();
\r
86 } catch (ParseException e) {
\r
95 * Computes a reasonable number of labels for a data range.
\r
97 * @param start start value
\r
98 * @param end final value
\r
99 * @param approxNumLabels desired number of labels
\r
100 * @return double[] array containing {start value, end value, increment}
\r
102 private static double[] computeLabels(final double start, final double end,
\r
103 final int approxNumLabels) {
\r
104 if (Math.abs(start - end) < 0.0000001f) {
\r
105 return new double[] { start, start, 0 };
\r
109 boolean switched = false;
\r
116 double xStep = roundUp(Math.abs(s - e) / approxNumLabels);
\r
117 // Compute x starting point so it is a multiple of xStep.
\r
118 double xStart = xStep * Math.ceil(s / xStep);
\r
119 double xEnd = xStep * Math.floor(e / xStep);
\r
121 return new double[] { xEnd, xStart, -1.0 * xStep };
\r
123 return new double[] { xStart, xEnd, xStep };
\r
127 * Given a number, round up to the nearest power of ten times 1, 2, or 5. The
\r
128 * argument must be strictly positive.
\r
130 private static double roundUp(final double val) {
\r
131 int exponent = (int) Math.floor(Math.log10(val));
\r
132 double rval = val * Math.pow(10, -exponent);
\r
135 } else if (rval > 2.0) {
\r
137 } else if (rval > 1.0) {
\r
140 rval *= Math.pow(10, exponent);
\r
145 * Transforms a list of Float values into an array of float.
\r
147 * @param values the list of Float
\r
148 * @return the array of floats
\r
150 public static float[] getFloats(List<Float> values) {
\r
151 int length = values.size();
\r
152 float[] result = new float[length];
\r
153 for (int i = 0; i < length; i++) {
\r
154 result[i] = values.get(i).floatValue();
\r
160 * Transforms a list of Double values into an array of double.
\r
162 * @param values the list of Double
\r
163 * @return the array of doubles
\r
165 public static double[] getDoubles(List<Double> values) {
\r
166 int length = values.size();
\r
167 double[] result = new double[length];
\r
168 for (int i = 0; i < length; i++) {
\r
169 result[i] = values.get(i).doubleValue();
\r