+/**\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.model;\r
+\r
+import java.io.Serializable;\r
+import java.util.Iterator;\r
+import java.util.SortedMap;\r
+\r
+import org.achartengine.util.IndexXYMap;\r
+import org.achartengine.util.MathHelper;\r
+import org.achartengine.util.XYEntry;\r
+\r
+/**\r
+ * An XY series encapsulates values for XY charts like line, time, area,\r
+ * scatter... charts.\r
+ */\r
+public class XYSeries implements Serializable {\r
+ /** The series title. */\r
+ private String mTitle;\r
+ /** A map to contain values for X and Y axes and index for each bundle */\r
+ private final IndexXYMap<Double, Double> mXY = new IndexXYMap<Double, Double>();\r
+ /** The minimum value for the X axis. */\r
+ private double mMinX = MathHelper.NULL_VALUE;\r
+ /** The maximum value for the X axis. */\r
+ private double mMaxX = -MathHelper.NULL_VALUE;\r
+ /** The minimum value for the Y axis. */\r
+ private double mMinY = MathHelper.NULL_VALUE;\r
+ /** The maximum value for the Y axis. */\r
+ private double mMaxY = -MathHelper.NULL_VALUE;\r
+ /** The scale number for this series. */\r
+ private final int mScaleNumber;\r
+\r
+ /**\r
+ * Builds a new XY series.\r
+ * \r
+ * @param title the series title.\r
+ */\r
+ public XYSeries(String title) {\r
+ this(title, 0);\r
+ }\r
+\r
+ /**\r
+ * Builds a new XY series.\r
+ * \r
+ * @param title the series title.\r
+ * @param scaleNumber the series scale number\r
+ */\r
+ public XYSeries(String title, int scaleNumber) {\r
+ mTitle = title;\r
+ mScaleNumber = scaleNumber;\r
+ initRange();\r
+ }\r
+\r
+ public int getScaleNumber() {\r
+ return mScaleNumber;\r
+ }\r
+\r
+ /**\r
+ * Initializes the range for both axes.\r
+ */\r
+ private void initRange() {\r
+ mMinX = MathHelper.NULL_VALUE;\r
+ mMaxX = -MathHelper.NULL_VALUE;\r
+ mMinY = MathHelper.NULL_VALUE;\r
+ mMaxY = -MathHelper.NULL_VALUE;\r
+ int length = getItemCount();\r
+ for (int k = 0; k < length; k++) {\r
+ double x = getX(k);\r
+ double y = getY(k);\r
+ updateRange(x, y);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Updates the range on both axes.\r
+ * \r
+ * @param x the new x value\r
+ * @param y the new y value\r
+ */\r
+ private void updateRange(double x, double y) {\r
+ mMinX = Math.min(mMinX, x);\r
+ mMaxX = Math.max(mMaxX, x);\r
+ mMinY = Math.min(mMinY, y);\r
+ mMaxY = Math.max(mMaxY, y);\r
+ }\r
+\r
+ /**\r
+ * Returns the series title.\r
+ * \r
+ * @return the series title\r
+ */\r
+ public String getTitle() {\r
+ return mTitle;\r
+ }\r
+\r
+ /**\r
+ * Sets the series title.\r
+ * \r
+ * @param title the series title\r
+ */\r
+ public void setTitle(String title) {\r
+ mTitle = title;\r
+ }\r
+\r
+ /**\r
+ * Adds a new value to the series.\r
+ * \r
+ * @param x the value for the X axis\r
+ * @param y the value for the Y axis\r
+ */\r
+ public synchronized void add(double x, double y) {\r
+ mXY.put(x, y);\r
+ updateRange(x, y);\r
+ }\r
+\r
+ /**\r
+ * Removes an existing value from the series.\r
+ * \r
+ * @param index the index in the series of the value to remove\r
+ */\r
+ public synchronized void remove(int index) {\r
+ XYEntry<Double, Double> removedEntry = mXY.removeByIndex(index);\r
+ double removedX = removedEntry.getKey();\r
+ double removedY = removedEntry.getValue();\r
+ if (removedX == mMinX || removedX == mMaxX || removedY == mMinY || removedY == mMaxY) {\r
+ initRange();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Removes all the existing values from the series.\r
+ */\r
+ public synchronized void clear() {\r
+ mXY.clear();\r
+ initRange();\r
+ }\r
+\r
+ /**\r
+ * Returns the X axis value at the specified index.\r
+ * \r
+ * @param index the index\r
+ * @return the X value\r
+ */\r
+ public synchronized double getX(int index) {\r
+ return mXY.getXByIndex(index);\r
+ }\r
+\r
+ /**\r
+ * Returns the Y axis value at the specified index.\r
+ * \r
+ * @param index the index\r
+ * @return the Y value\r
+ */\r
+ public synchronized double getY(int index) {\r
+ return mXY.getYByIndex(index);\r
+ }\r
+\r
+ /**\r
+ * Returns submap of x and y values according to the given start and end\r
+ * \r
+ * @param start start x value\r
+ * @param stop stop x value\r
+ * @return a submap of x and y values\r
+ */\r
+ public synchronized SortedMap<Double, Double> getRange(double start, double stop,\r
+ int beforeAfterPoints) {\r
+ // we need to add one point before the start and one point after the end (if\r
+ // there are any)\r
+ // to ensure that line doesn't end before the end of the screen\r
+\r
+ // this would be simply: start = mXY.lowerKey(start) but NavigableMap is\r
+ // available since API 9\r
+ SortedMap<Double, Double> headMap = mXY.headMap(start);\r
+ if (!headMap.isEmpty()) {\r
+ start = headMap.lastKey();\r
+ }\r
+\r
+ // this would be simply: end = mXY.higherKey(end) but NavigableMap is\r
+ // available since API 9\r
+ // so we have to do this hack in order to support older versions\r
+ SortedMap<Double, Double> tailMap = mXY.tailMap(stop);\r
+ if (!tailMap.isEmpty()) {\r
+ Iterator<Double> tailIterator = tailMap.keySet().iterator();\r
+ Double next = tailIterator.next();\r
+ if (tailIterator.hasNext()) {\r
+ stop = tailIterator.next();\r
+ } else {\r
+ stop += next;\r
+ }\r
+ }\r
+ return mXY.subMap(start, stop);\r
+ }\r
+\r
+ public int getIndexForKey(double key) {\r
+ return mXY.getIndexForKey(key);\r
+ }\r
+\r
+ /**\r
+ * Returns the series item count.\r
+ * \r
+ * @return the series item count\r
+ */\r
+ public synchronized int getItemCount() {\r
+ return mXY.size();\r
+ }\r
+\r
+ /**\r
+ * Returns the minimum value on the X axis.\r
+ * \r
+ * @return the X axis minimum value\r
+ */\r
+ public double getMinX() {\r
+ return mMinX;\r
+ }\r
+\r
+ /**\r
+ * Returns the minimum value on the Y axis.\r
+ * \r
+ * @return the Y axis minimum value\r
+ */\r
+ public double getMinY() {\r
+ return mMinY;\r
+ }\r
+\r
+ /**\r
+ * Returns the maximum value on the X axis.\r
+ * \r
+ * @return the X axis maximum value\r
+ */\r
+ public double getMaxX() {\r
+ return mMaxX;\r
+ }\r
+\r
+ /**\r
+ * Returns the maximum value on the Y axis.\r
+ * \r
+ * @return the Y axis maximum value\r
+ */\r
+ public double getMaxY() {\r
+ return mMaxY;\r
+ }\r
+}\r