Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / android-libraries / achartengine / src / org / achartengine / chart / DialChart.java
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/DialChart.java b/android-libraries/achartengine/src/org/achartengine/chart/DialChart.java
new file mode 100644 (file)
index 0000000..ebfcbbb
--- /dev/null
@@ -0,0 +1,236 @@
+/**\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.chart;\r
+\r
+import org.achartengine.model.CategorySeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.DialRenderer;\r
+import org.achartengine.renderer.DialRenderer.Type;\r
+import org.achartengine.util.MathHelper;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Align;\r
+import android.graphics.Paint.Style;\r
+\r
+/**\r
+ * The dial chart rendering class.\r
+ */\r
+public class DialChart extends RoundChart {\r
+  /** The radius of the needle. */\r
+  private static final int NEEDLE_RADIUS = 10;\r
+  /** The series renderer. */\r
+  private DialRenderer mRenderer;\r
+\r
+  /**\r
+   * Builds a new dial chart instance.\r
+   * \r
+   * @param dataset the series dataset\r
+   * @param renderer the dial renderer\r
+   */\r
+  public DialChart(CategorySeries dataset, DialRenderer renderer) {\r
+    super(dataset, renderer);\r
+    mRenderer = renderer;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the dial chart.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param height the height of the view to draw to\r
+   * @param paint the paint\r
+   */\r
+  @Override\r
+  public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {\r
+    paint.setAntiAlias(mRenderer.isAntialiasing());\r
+    paint.setStyle(Style.FILL);\r
+    paint.setTextSize(mRenderer.getLabelsTextSize());\r
+    int legendSize = getLegendSize(mRenderer, height / 5, 0);\r
+    int left = x;\r
+    int top = y;\r
+    int right = x + width;\r
+\r
+    int sLength = mDataset.getItemCount();\r
+    String[] titles = new String[sLength];\r
+    for (int i = 0; i < sLength; i++) {\r
+      titles[i] = mDataset.getCategory(i);\r
+    }\r
+\r
+    if (mRenderer.isFitLegend()) {\r
+      legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,\r
+          paint, true);\r
+    }\r
+    int bottom = y + height - legendSize;\r
+    drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);\r
+\r
+    int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));\r
+    int radius = (int) (mRadius * 0.35 * mRenderer.getScale());\r
+    if (mCenterX == NO_VALUE) {\r
+      mCenterX = (left + right) / 2;\r
+    }\r
+    if (mCenterY == NO_VALUE) {\r
+      mCenterY = (bottom + top) / 2;\r
+    }\r
+    float shortRadius = radius * 0.9f;\r
+    float longRadius = radius * 1.1f;\r
+    double min = mRenderer.getMinValue();\r
+    double max = mRenderer.getMaxValue();\r
+    double angleMin = mRenderer.getAngleMin();\r
+    double angleMax = mRenderer.getAngleMax();\r
+    if (!mRenderer.isMinValueSet() || !mRenderer.isMaxValueSet()) {\r
+      int count = mRenderer.getSeriesRendererCount();\r
+      for (int i = 0; i < count; i++) {\r
+        double value = mDataset.getValue(i);\r
+        if (!mRenderer.isMinValueSet()) {\r
+          min = Math.min(min, value);\r
+        }\r
+        if (!mRenderer.isMaxValueSet()) {\r
+          max = Math.max(max, value);\r
+        }\r
+      }\r
+    }\r
+    if (min == max) {\r
+      min = min * 0.5;\r
+      max = max * 1.5;\r
+    }\r
+\r
+    paint.setColor(mRenderer.getLabelsColor());\r
+    double minorTicks = mRenderer.getMinorTicksSpacing();\r
+    double majorTicks = mRenderer.getMajorTicksSpacing();\r
+    if (minorTicks == MathHelper.NULL_VALUE) {\r
+      minorTicks = (max - min) / 30;\r
+    }\r
+    if (majorTicks == MathHelper.NULL_VALUE) {\r
+      majorTicks = (max - min) / 10;\r
+    }\r
+    drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, radius,\r
+        minorTicks, paint, false);\r
+    drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, shortRadius,\r
+        majorTicks, paint, true);\r
+\r
+    int count = mRenderer.getSeriesRendererCount();\r
+    for (int i = 0; i < count; i++) {\r
+      double angle = getAngleForValue(mDataset.getValue(i), angleMin, angleMax, min, max);\r
+      paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());\r
+      boolean type = mRenderer.getVisualTypeForIndex(i) == Type.ARROW;\r
+      drawNeedle(canvas, angle, mCenterX, mCenterY, shortRadius, type, paint);\r
+    }\r
+    drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);\r
+    drawTitle(canvas, x, y, width, paint);\r
+  }\r
+\r
+  /**\r
+   * Returns the angle for a specific chart value.\r
+   * \r
+   * @param value the chart value\r
+   * @param minAngle the minimum chart angle value\r
+   * @param maxAngle the maximum chart angle value\r
+   * @param min the minimum chart value\r
+   * @param max the maximum chart value\r
+   * @return the angle\r
+   */\r
+  private double getAngleForValue(double value, double minAngle, double maxAngle, double min,\r
+      double max) {\r
+    double angleDiff = maxAngle - minAngle;\r
+    double diff = max - min;\r
+    return Math.toRadians(minAngle + (value - min) * angleDiff / diff);\r
+  }\r
+\r
+  /**\r
+   * Draws the chart tick lines.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param min the minimum chart value\r
+   * @param max the maximum chart value\r
+   * @param minAngle the minimum chart angle value\r
+   * @param maxAngle the maximum chart angle value\r
+   * @param centerX the center x value\r
+   * @param centerY the center y value\r
+   * @param longRadius the long radius\r
+   * @param shortRadius the short radius\r
+   * @param ticks the tick spacing\r
+   * @param paint the paint settings\r
+   * @param labels paint the labels\r
+   * @return the angle\r
+   */\r
+  private void drawTicks(Canvas canvas, double min, double max, double minAngle, double maxAngle,\r
+      int centerX, int centerY, double longRadius, double shortRadius, double ticks, Paint paint,\r
+      boolean labels) {\r
+    for (double i = min; i <= max; i += ticks) {\r
+      double angle = getAngleForValue(i, minAngle, maxAngle, min, max);\r
+      double sinValue = Math.sin(angle);\r
+      double cosValue = Math.cos(angle);\r
+      int x1 = Math.round(centerX + (float) (shortRadius * sinValue));\r
+      int y1 = Math.round(centerY + (float) (shortRadius * cosValue));\r
+      int x2 = Math.round(centerX + (float) (longRadius * sinValue));\r
+      int y2 = Math.round(centerY + (float) (longRadius * cosValue));\r
+      canvas.drawLine(x1, y1, x2, y2, paint);\r
+      if (labels) {\r
+        paint.setTextAlign(Align.LEFT);\r
+        if (x1 <= x2) {\r
+          paint.setTextAlign(Align.RIGHT);\r
+        }\r
+        String text = i + "";\r
+        if (Math.round(i) == (long) i) {\r
+          text = (long) i + "";\r
+        }\r
+        canvas.drawText(text, x1, y1, paint);\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the angle for a specific chart value.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param angle the needle angle value\r
+   * @param centerX the center x value\r
+   * @param centerY the center y value\r
+   * @param radius the radius\r
+   * @param arrow if a needle or an arrow to be painted\r
+   * @param paint the paint settings\r
+   * @return the angle\r
+   */\r
+  private void drawNeedle(Canvas canvas, double angle, int centerX, int centerY, double radius,\r
+      boolean arrow, Paint paint) {\r
+    double diff = Math.toRadians(90);\r
+    int needleSinValue = (int) (NEEDLE_RADIUS * Math.sin(angle - diff));\r
+    int needleCosValue = (int) (NEEDLE_RADIUS * Math.cos(angle - diff));\r
+    int needleX = (int) (radius * Math.sin(angle));\r
+    int needleY = (int) (radius * Math.cos(angle));\r
+    int needleCenterX = centerX + needleX;\r
+    int needleCenterY = centerY + needleY;\r
+    float[] points;\r
+    if (arrow) {\r
+      int arrowBaseX = centerX + (int) (radius * 0.85 * Math.sin(angle));\r
+      int arrowBaseY = centerY + (int) (radius * 0.85 * Math.cos(angle));\r
+      points = new float[] { arrowBaseX - needleSinValue, arrowBaseY - needleCosValue,\r
+          needleCenterX, needleCenterY, arrowBaseX + needleSinValue, arrowBaseY + needleCosValue };\r
+      float width = paint.getStrokeWidth();\r
+      paint.setStrokeWidth(5);\r
+      canvas.drawLine(centerX, centerY, needleCenterX, needleCenterY, paint);\r
+      paint.setStrokeWidth(width);\r
+    } else {\r
+      points = new float[] { centerX - needleSinValue, centerY - needleCosValue, needleCenterX,\r
+          needleCenterY, centerX + needleSinValue, centerY + needleCosValue };\r
+    }\r
+    drawPath(canvas, points, paint, true);\r
+  }\r
+\r
+}\r