create changelog entry
[debian/openrocket] / android-libraries / achartengine / src / org / achartengine / chart / PieMapper.java
1 /**
2  * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
3  *  
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *  
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *  
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.achartengine.chart;
17
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.achartengine.model.Point;
23 import org.achartengine.model.SeriesSelection;
24
25 /**
26  * PieChart Segment Selection Management.
27  */
28 public class PieMapper implements Serializable {
29
30   private List<PieSegment> mPieSegmentList = new ArrayList<PieSegment>();
31
32   private int mPieChartRadius;
33
34   private int mCenterX, mCenterY;
35
36   /**
37    * Set PieChart location on screen.
38    * 
39    * @param pieRadius
40    * @param centerX
41    * @param centerY
42    */
43   public void setDimensions(int pieRadius, int centerX, int centerY) {
44     mPieChartRadius = pieRadius;
45     mCenterX = centerX;
46     mCenterY = centerY;
47   }
48
49   /**
50    * If we have all PieChart Config then there is no point in reloading it
51    * 
52    * @param datasetSize
53    * @return true if cfg for each segment is present
54    */
55   public boolean areAllSegmentPresent(int datasetSize) {
56     return mPieSegmentList.size() == datasetSize;
57   }
58   
59   /**
60    * Add configuration for a PieChart Segment
61    * 
62    * @param dataIndex
63    * @param value
64    * @param startAngle
65    * @param angle
66    */
67   public void addPieSegment(int dataIndex, float value, float startAngle, float angle) {
68     mPieSegmentList.add(new PieSegment(dataIndex, value, startAngle, angle));
69   }
70   
71   /**
72    * Clears the pie segments list.
73    */
74   public void clearPieSegments() {
75     mPieSegmentList.clear();
76   }
77
78   /**
79    * Fetches angle relative to pie chart center point where 3 O'Clock is 0 and
80    * 12 O'Clock is 270degrees
81    * 
82    * @param screenPoint
83    * @return angle in degress from 0-360.
84    */
85   public double getAngle(Point screenPoint) {
86     double dx = screenPoint.getX() - mCenterX;
87     // Minus to correct for coord re-mapping
88     double dy = -(screenPoint.getY() - mCenterY);
89
90     double inRads = Math.atan2(dy, dx);
91
92     // We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12
93     // O'clock
94     if (inRads < 0)
95       inRads = Math.abs(inRads);
96     else
97       inRads = 2 * Math.PI - inRads;
98
99     return Math.toDegrees(inRads);
100   }
101
102   /**
103    * Checks if Point falls within PieChart
104    * 
105    * @param screenPoint
106    * @return true if in PieChart
107    */
108   public boolean isOnPieChart(Point screenPoint) {
109     // Using a bit of Pythagoras
110     // inside circle if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
111
112     double sqValue = (Math.pow(mCenterX - screenPoint.getX(), 2) + Math.pow(
113         mCenterY - screenPoint.getY(), 2));
114
115     double radiusSquared = mPieChartRadius * mPieChartRadius;
116     boolean isOnPieChart = sqValue <= radiusSquared;
117     return isOnPieChart;
118   }
119
120   /**
121    * Fetches the SeriesSelection for the PieSegment selected.
122    * 
123    * @param screenPoint - the user tap location
124    * @return null if screen point is not in PieChart or its config if it is
125    */
126   public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint) {
127     if (isOnPieChart(screenPoint)) {
128       double angleFromPieCenter = getAngle(screenPoint);
129
130       for (PieSegment pieSeg : mPieSegmentList) {
131         if (pieSeg.isInSegment(angleFromPieCenter)) {
132           return new SeriesSelection(0, pieSeg.getDataIndex(), pieSeg.getValue(),
133               pieSeg.getValue());
134         }
135       }
136     }
137     return null;
138   }
139 }